Merge "Add SubscriptionManager APIs for satellite communication."
diff --git a/Android.bp b/Android.bp
index cfab18e..ea7ced9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -224,6 +224,7 @@
"android.hardware.radio.messaging-V2-java",
"android.hardware.radio.modem-V2-java",
"android.hardware.radio.network-V2-java",
+ "android.hardware.radio.satellite-V1-java",
"android.hardware.radio.sim-V2-java",
"android.hardware.radio.voice-V2-java",
"android.hardware.thermal-V1.0-java-constants",
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 439f54c..7ed4d35 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -800,22 +800,12 @@
* if {@code null} is passed as the {@code targetHandler} parameter.
*
* <p class="note"><strong>Note:</strong>
- * Starting with {@link Build.VERSION_CODES#S}, apps targeting SDK level 31 or higher
- * need to request the
- * {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use this
- * API, unless the app is exempt from battery restrictions.
- * The user and the system can revoke this permission via the special app access screen in
- * Settings.
+ * On previous android versions {@link Build.VERSION_CODES#S} and
+ * {@link Build.VERSION_CODES#TIRAMISU}, apps targeting SDK level 31 or higher needed to hold
+ * the {@link Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM} permission to use
+ * this API, unless the app was exempt from battery restrictions.
*
- * <p class="note"><strong>Note:</strong>
- * Exact alarms should only be used for user-facing features.
- * For more details, see <a
- * href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
- * Exact alarm permission</a>.
- *
- * @see Manifest.permission#SCHEDULE_EXACT_ALARM SCHEDULE_EXACT_ALARM
*/
- @RequiresPermission(value = Manifest.permission.SCHEDULE_EXACT_ALARM, conditional = true)
public void setExact(@AlarmType int type, long triggerAtMillis, @Nullable String tag,
@NonNull OnAlarmListener listener, @Nullable Handler targetHandler) {
setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, null, listener, tag,
@@ -949,7 +939,8 @@
* {@link #setExact(int, long, String, OnAlarmListener, Handler)} instead.
*
* <p>
- * Note that using this API requires you to hold
+ * Note that on previous Android versions {@link Build.VERSION_CODES#S} and
+ * {@link Build.VERSION_CODES#TIRAMISU}, using this API required you to hold
* {@link Manifest.permission#SCHEDULE_EXACT_ALARM}, unless you are on the system's power
* allowlist. This can be set, for example, by marking the app as {@code <allow-in-power-save>}
* within the system config.
@@ -970,9 +961,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {
- Manifest.permission.UPDATE_DEVICE_STATS,
- Manifest.permission.SCHEDULE_EXACT_ALARM}, conditional = true)
+ @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
public void setExact(@AlarmType int type, long triggerAtMillis, @Nullable String tag,
@NonNull Executor executor, @NonNull WorkSource workSource,
@NonNull OnAlarmListener listener) {
@@ -1283,9 +1272,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(allOf = {
- Manifest.permission.UPDATE_DEVICE_STATS,
- Manifest.permission.SCHEDULE_EXACT_ALARM}, conditional = true)
+ @RequiresPermission(Manifest.permission.UPDATE_DEVICE_STATS)
public void setExactAndAllowWhileIdle(@AlarmType int type, long triggerAtMillis,
@Nullable String tag, @NonNull Executor executor, @Nullable WorkSource workSource,
@NonNull OnAlarmListener listener) {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index fd2bb13..69fe85e 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -92,6 +92,14 @@
* Caller had USE_EXACT_ALARM permission.
*/
static final int EXACT_ALLOW_REASON_POLICY_PERMISSION = 3;
+ /**
+ * Caller used a listener alarm, which does not need permission to be exact.
+ */
+ static final int EXACT_ALLOW_REASON_LISTENER = 4;
+ /**
+ * Caller used a prioritized alarm, which does not need permission to be exact.
+ */
+ static final int EXACT_ALLOW_REASON_PRIORITIZED = 5;
public final int type;
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index d6d51e0..e41eb00 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -47,9 +47,11 @@
import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
+import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_LISTENER;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION;
+import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PRIORITIZED;
import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
import static com.android.server.alarm.Alarm.TARE_POLICY_INDEX;
import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_ALARM_CANCELLED;
@@ -2890,12 +2892,23 @@
// The API doesn't allow using both together.
flags &= ~FLAG_ALLOW_WHILE_IDLE;
// Prioritized alarms don't need any extra permission to be exact.
+ if (exact) {
+ exactAllowReason = EXACT_ALLOW_REASON_PRIORITIZED;
+ }
} else if (exact || allowWhileIdle) {
final boolean needsPermission;
boolean lowerQuota;
if (isExactAlarmChangeEnabled(callingPackage, callingUserId)) {
- needsPermission = exact;
- lowerQuota = !exact;
+ if (directReceiver == null) {
+ needsPermission = exact;
+ lowerQuota = !exact;
+ } else {
+ needsPermission = false;
+ lowerQuota = allowWhileIdle;
+ if (exact) {
+ exactAllowReason = EXACT_ALLOW_REASON_LISTENER;
+ }
+ }
if (exact) {
idleOptions = (alarmClock != null) ? mOptsWithFgsForAlarmClock.toBundle()
: mOptsWithFgs.toBundle();
@@ -2931,11 +2944,9 @@
throw new SecurityException(errorMessage);
}
// If the app is on the full system power allow-list (not except-idle),
- // or the user-elected allow-list, or we're in a soft failure mode, we still
- // allow the alarms.
- // In both cases, ALLOW_WHILE_IDLE alarms get a lower quota equivalent to
- // what pre-S apps got. Note that user-allow-listed apps don't use the flag
- // ALLOW_WHILE_IDLE.
+ // or the user-elected allow-list, we allow exact alarms.
+ // ALLOW_WHILE_IDLE alarms get a lower quota equivalent to what pre-S apps
+ // got. Note that user-allow-listed apps don't use FLAG_ALLOW_WHILE_IDLE.
// We grant temporary allow-list to allow-while-idle alarms but without FGS
// capability. AlarmClock alarms do not get the temporary allow-list.
// This is consistent with pre-S behavior. Note that apps that are in
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
index 75ed616..28acb45 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/MetricsHelper.java
@@ -18,9 +18,11 @@
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
+import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__LISTENER;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
+import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PRIORITIZED;
import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
import android.app.ActivityManager;
@@ -84,14 +86,18 @@
private static int reasonToStatsReason(int reasonCode) {
switch (reasonCode) {
- case Alarm.EXACT_ALLOW_REASON_ALLOW_LIST:
- return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
case Alarm.EXACT_ALLOW_REASON_PERMISSION:
return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
+ case Alarm.EXACT_ALLOW_REASON_ALLOW_LIST:
+ return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
case Alarm.EXACT_ALLOW_REASON_COMPAT:
return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
case Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION:
return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
+ case Alarm.EXACT_ALLOW_REASON_LISTENER:
+ return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__LISTENER;
+ case Alarm.EXACT_ALLOW_REASON_PRIORITIZED:
+ return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PRIORITIZED;
default:
return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index bf8984f..62d97358 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -158,33 +158,37 @@
* state (excluding {@link ActivityManager#PROCESS_STATE_TOP} for a currently active user.
*/
static final int WORK_TYPE_FGS = 1 << 1;
+ /** The job is allowed to run as a user-initiated job for a currently active user. */
+ static final int WORK_TYPE_UI = 1 << 2;
/** The job is allowed to run as an expedited job for a currently active user. */
- static final int WORK_TYPE_EJ = 1 << 2;
+ static final int WORK_TYPE_EJ = 1 << 3;
/**
* The job does not satisfy any of the conditions for {@link #WORK_TYPE_TOP},
* {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a currently active user, so
* can run as a background job.
*/
- static final int WORK_TYPE_BG = 1 << 3;
+ static final int WORK_TYPE_BG = 1 << 4;
/**
* The job is for an app in a {@link ActivityManager#PROCESS_STATE_FOREGROUND_SERVICE} or higher
- * state, or is allowed to run as an expedited job, but is for a completely background user.
+ * state, or is allowed to run as an expedited or user-initiated job,
+ * but is for a completely background user.
*/
- static final int WORK_TYPE_BGUSER_IMPORTANT = 1 << 4;
+ static final int WORK_TYPE_BGUSER_IMPORTANT = 1 << 5;
/**
* The job does not satisfy any of the conditions for {@link #WORK_TYPE_TOP},
* {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a completely background user,
* so can run as a background user job.
*/
- static final int WORK_TYPE_BGUSER = 1 << 5;
+ static final int WORK_TYPE_BGUSER = 1 << 6;
@VisibleForTesting
- static final int NUM_WORK_TYPES = 6;
+ static final int NUM_WORK_TYPES = 7;
private static final int ALL_WORK_TYPES = (1 << NUM_WORK_TYPES) - 1;
@IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = {
WORK_TYPE_NONE,
WORK_TYPE_TOP,
WORK_TYPE_FGS,
+ WORK_TYPE_UI,
WORK_TYPE_EJ,
WORK_TYPE_BG,
WORK_TYPE_BGUSER_IMPORTANT,
@@ -203,6 +207,8 @@
return "TOP";
case WORK_TYPE_FGS:
return "FGS";
+ case WORK_TYPE_UI:
+ return "UI";
case WORK_TYPE_EJ:
return "EJ";
case WORK_TYPE_BG:
@@ -238,8 +244,9 @@
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, .4f),
Pair.create(WORK_TYPE_FGS, .2f),
- Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
+ Pair.create(WORK_TYPE_UI, .1f),
+ Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .05f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, .5f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .25f),
@@ -250,6 +257,7 @@
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, .4f),
Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_UI, .1f),
Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .1f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
@@ -260,8 +268,9 @@
new WorkTypeConfig("screen_on_low", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
+ List.of(Pair.create(WORK_TYPE_TOP, .6f),
Pair.create(WORK_TYPE_FGS, .1f),
+ Pair.create(WORK_TYPE_UI, .1f),
Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
@@ -271,9 +280,10 @@
new WorkTypeConfig("screen_on_critical", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
+ List.of(Pair.create(WORK_TYPE_TOP, .7f),
Pair.create(WORK_TYPE_FGS, .1f),
- Pair.create(WORK_TYPE_EJ, .1f)),
+ Pair.create(WORK_TYPE_UI, .1f),
+ Pair.create(WORK_TYPE_EJ, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 6),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 6),
@@ -287,8 +297,9 @@
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, .3f),
Pair.create(WORK_TYPE_FGS, .2f),
- Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
+ Pair.create(WORK_TYPE_UI, .2f),
+ Pair.create(WORK_TYPE_EJ, .15f), Pair.create(WORK_TYPE_BG, .1f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, .6f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .2f),
@@ -299,8 +310,9 @@
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, .3f),
Pair.create(WORK_TYPE_FGS, .2f),
- Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
- Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
+ Pair.create(WORK_TYPE_UI, .2f),
+ Pair.create(WORK_TYPE_EJ, .15f), Pair.create(WORK_TYPE_BG, .1f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, .5f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
@@ -309,9 +321,11 @@
new WorkTypeConfig("screen_off_low", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 6 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, .4f),
- Pair.create(WORK_TYPE_FGS, .1f),
- Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f)),
+ List.of(Pair.create(WORK_TYPE_TOP, .3f),
+ Pair.create(WORK_TYPE_FGS, .15f),
+ Pair.create(WORK_TYPE_UI, .15f),
+ Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .05f),
+ Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, .25f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
@@ -320,9 +334,10 @@
new WorkTypeConfig("screen_off_critical", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, .5f),
+ List.of(Pair.create(WORK_TYPE_TOP, .3f),
Pair.create(WORK_TYPE_FGS, .1f),
- Pair.create(WORK_TYPE_EJ, .1f)),
+ Pair.create(WORK_TYPE_UI, .1f),
+ Pair.create(WORK_TYPE_EJ, .05f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, .1f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
@@ -2097,10 +2112,12 @@
if (js.shouldTreatAsExpeditedJob()) {
classification |= WORK_TYPE_EJ;
+ } else if (js.shouldTreatAsUserInitiatedJob()) {
+ classification |= WORK_TYPE_UI;
}
} else {
if (js.lastEvaluatedBias >= JobInfo.BIAS_FOREGROUND_SERVICE
- || js.shouldTreatAsExpeditedJob()) {
+ || js.shouldTreatAsExpeditedJob() || js.shouldTreatAsUserInitiatedJob()) {
classification |= WORK_TYPE_BGUSER_IMPORTANT;
}
// BGUSER_IMPORTANT jobs can also run as BGUSER jobs, so not an 'else' here.
@@ -2120,6 +2137,7 @@
static final String KEY_PREFIX_MAX_RATIO = KEY_PREFIX_MAX + "ratio_";
private static final String KEY_PREFIX_MAX_RATIO_TOP = KEY_PREFIX_MAX_RATIO + "top_";
private static final String KEY_PREFIX_MAX_RATIO_FGS = KEY_PREFIX_MAX_RATIO + "fgs_";
+ private static final String KEY_PREFIX_MAX_RATIO_UI = KEY_PREFIX_MAX_RATIO + "ui_";
private static final String KEY_PREFIX_MAX_RATIO_EJ = KEY_PREFIX_MAX_RATIO + "ej_";
private static final String KEY_PREFIX_MAX_RATIO_BG = KEY_PREFIX_MAX_RATIO + "bg_";
private static final String KEY_PREFIX_MAX_RATIO_BGUSER = KEY_PREFIX_MAX_RATIO + "bguser_";
@@ -2129,6 +2147,7 @@
static final String KEY_PREFIX_MIN_RATIO = KEY_PREFIX_MIN + "ratio_";
private static final String KEY_PREFIX_MIN_RATIO_TOP = KEY_PREFIX_MIN_RATIO + "top_";
private static final String KEY_PREFIX_MIN_RATIO_FGS = KEY_PREFIX_MIN_RATIO + "fgs_";
+ private static final String KEY_PREFIX_MIN_RATIO_UI = KEY_PREFIX_MIN_RATIO + "ui_";
private static final String KEY_PREFIX_MIN_RATIO_EJ = KEY_PREFIX_MIN_RATIO + "ej_";
private static final String KEY_PREFIX_MIN_RATIO_BG = KEY_PREFIX_MIN_RATIO + "bg_";
private static final String KEY_PREFIX_MIN_RATIO_BGUSER = KEY_PREFIX_MIN_RATIO + "bguser_";
@@ -2209,6 +2228,9 @@
final int maxFgs = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier, WORK_TYPE_FGS, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_FGS, maxFgs);
+ final int maxUi = getMaxValue(properties,
+ KEY_PREFIX_MAX_RATIO_UI + mConfigIdentifier, WORK_TYPE_UI, oneIntBits);
+ mMaxAllowedSlots.put(WORK_TYPE_UI, maxUi);
final int maxEj = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_EJ, maxEj);
@@ -2237,6 +2259,12 @@
0, Math.min(maxFgs, remaining));
mMinReservedSlots.put(WORK_TYPE_FGS, minFgs);
remaining -= minFgs;
+ // Ensure ui is in the range [0, min(maxUi, remaining)]
+ final int minUi = getMinValue(properties,
+ KEY_PREFIX_MIN_RATIO_UI + mConfigIdentifier, WORK_TYPE_UI,
+ 0, Math.min(maxUi, remaining));
+ mMinReservedSlots.put(WORK_TYPE_UI, minUi);
+ remaining -= minUi;
// Ensure ej is in the range [0, min(maxEj, remaining)]
final int minEj = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ,
@@ -2313,6 +2341,12 @@
pw.print(KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_FGS))
.println();
+ pw.print(KEY_PREFIX_MIN_RATIO_UI + mConfigIdentifier,
+ mMinReservedSlots.get(WORK_TYPE_UI))
+ .println();
+ pw.print(KEY_PREFIX_MAX_RATIO_UI + mConfigIdentifier,
+ mMaxAllowedSlots.get(WORK_TYPE_UI))
+ .println();
pw.print(KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_EJ))
.println();
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java b/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
index f27da4a..06333f1 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
@@ -408,7 +408,7 @@
if (report.screenOffDurationMs > 0) {
pw.print(padStringWithSpaces(String.format("%d mAh (%.2f%%/hr)",
report.screenOffDischargeMah,
- 1.0 * report.screenOffDischargeMah * HOUR_IN_MILLIS
+ 100.0 * report.screenOffDischargeMah * HOUR_IN_MILLIS
/ (batteryCapacityMah * report.screenOffDurationMs)),
statColsLength));
} else {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 4001d9b..08c1a0c 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -209,8 +209,10 @@
@GuardedBy("mLock")
private int mCurrentBatteryLevel;
- // TODO(250007395): make configurable per device
- private final int mTargetBackgroundBatteryLifeHours;
+ // TODO(250007395): make configurable per device (via config.xml)
+ private final int mDefaultTargetBackgroundBatteryLifeHours;
+ @GuardedBy("mLock")
+ private int mTargetBackgroundBatteryLifeHours;
private final IAppOpsCallback mApbListener = new IAppOpsCallback.Stub() {
@Override
@@ -353,10 +355,11 @@
mConfigObserver = new ConfigObserver(mHandler, context);
- mTargetBackgroundBatteryLifeHours =
+ mDefaultTargetBackgroundBatteryLifeHours =
mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
- ? 200 // ~ 0.5%/hr
- : 100; // ~ 1%/hr
+ ? 100 // ~ 1.0%/hr
+ : 40; // ~ 2.5%/hr
+ mTargetBackgroundBatteryLifeHours = mDefaultTargetBackgroundBatteryLifeHours;
publishLocalService(EconomyManagerInternal.class, new LocalService());
}
@@ -1483,6 +1486,8 @@
private class ConfigObserver extends ContentObserver
implements DeviceConfig.OnPropertiesChangedListener {
private static final String KEY_ENABLE_TIP3 = "enable_tip3";
+ private static final String KEY_TARGET_BACKGROUND_BATTERY_LIFE_HOURS =
+ "target_bg_battery_life_hrs";
private static final boolean DEFAULT_ENABLE_TIP3 = true;
@@ -1541,6 +1546,13 @@
case KEY_ENABLE_TIP3:
ENABLE_TIP3 = properties.getBoolean(name, DEFAULT_ENABLE_TIP3);
break;
+ case KEY_TARGET_BACKGROUND_BATTERY_LIFE_HOURS:
+ synchronized (mLock) {
+ mTargetBackgroundBatteryLifeHours = properties.getInt(name,
+ mDefaultTargetBackgroundBatteryLifeHours);
+ maybeAdjustDesiredStockLevelLocked();
+ }
+ break;
default:
if (!economicPolicyUpdated
&& (name.startsWith("am") || name.startsWith("js")
@@ -1670,6 +1682,12 @@
pw.print("/");
pw.println(cakeToString(mScribe.getSatiatedConsumptionLimitLocked()));
+ pw.print("Target bg battery life (hours): ");
+ pw.print(mTargetBackgroundBatteryLifeHours);
+ pw.print(" (");
+ pw.print(String.format("%.2f", 100f / mTargetBackgroundBatteryLifeHours));
+ pw.println("%/hr)");
+
final long remainingConsumable = mScribe.getRemainingConsumableCakesLocked();
pw.print("Goods remaining: ");
pw.print(cakeToString(remainingConsumable));
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
index b41c0d1..66327fd 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -717,8 +717,8 @@
out.startTag(null, XML_TAG_USER);
out.attributeInt(null, XML_ATTR_USER_ID, userId);
out.attributeLong(null, XML_ATTR_TIME_SINCE_FIRST_SETUP_MS,
- mRealtimeSinceUsersAddedOffsets.get(userId,
- mLoadedTimeSinceFirstSetup + SystemClock.elapsedRealtime()));
+ mRealtimeSinceUsersAddedOffsets.get(userId, mLoadedTimeSinceFirstSetup)
+ + SystemClock.elapsedRealtime());
for (int pIdx = mLedgers.numElementsForKey(userId) - 1; pIdx >= 0; --pIdx) {
final String pkgName = mLedgers.keyAt(uIdx, pIdx);
final Ledger ledger = mLedgers.get(userId, pkgName);
diff --git a/core/api/current.txt b/core/api/current.txt
index 38f0481..c811a09 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -96,7 +96,6 @@
field public static final String FOREGROUND_SERVICE_CAMERA = "android.permission.FOREGROUND_SERVICE_CAMERA";
field public static final String FOREGROUND_SERVICE_CONNECTED_DEVICE = "android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE";
field public static final String FOREGROUND_SERVICE_DATA_SYNC = "android.permission.FOREGROUND_SERVICE_DATA_SYNC";
- field public static final String FOREGROUND_SERVICE_FILE_MANAGEMENT = "android.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT";
field public static final String FOREGROUND_SERVICE_HEALTH = "android.permission.FOREGROUND_SERVICE_HEALTH";
field public static final String FOREGROUND_SERVICE_LOCATION = "android.permission.FOREGROUND_SERVICE_LOCATION";
field public static final String FOREGROUND_SERVICE_MEDIA_PLAYBACK = "android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK";
@@ -4678,7 +4677,7 @@
method @RequiresPermission(android.Manifest.permission.SCHEDULE_EXACT_ALARM) public void setAlarmClock(@NonNull android.app.AlarmManager.AlarmClockInfo, @NonNull android.app.PendingIntent);
method public void setAndAllowWhileIdle(int, long, @NonNull android.app.PendingIntent);
method @RequiresPermission(value=android.Manifest.permission.SCHEDULE_EXACT_ALARM, conditional=true) public void setExact(int, long, @NonNull android.app.PendingIntent);
- method @RequiresPermission(value=android.Manifest.permission.SCHEDULE_EXACT_ALARM, conditional=true) public void setExact(int, long, @Nullable String, @NonNull android.app.AlarmManager.OnAlarmListener, @Nullable android.os.Handler);
+ method public void setExact(int, long, @Nullable String, @NonNull android.app.AlarmManager.OnAlarmListener, @Nullable android.os.Handler);
method @RequiresPermission(value=android.Manifest.permission.SCHEDULE_EXACT_ALARM, conditional=true) public void setExactAndAllowWhileIdle(int, long, @NonNull android.app.PendingIntent);
method public void setInexactRepeating(int, long, long, @NonNull android.app.PendingIntent);
method public void setRepeating(int, long, long, @NonNull android.app.PendingIntent);
@@ -7413,6 +7412,7 @@
method public void dump(android.util.Printer, String);
method public android.content.pm.ActivityInfo getActivityInfo();
method @NonNull public android.content.ComponentName getComponent();
+ method public int getHeadlessDeviceOwnerMode();
method public String getPackageName();
method public String getReceiverName();
method public String getTagForPolicy(int);
@@ -7424,6 +7424,8 @@
method public boolean usesPolicy(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.DeviceAdminInfo> CREATOR;
+ field public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1; // 0x1
+ field public static final int HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED = 0; // 0x0
field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7
field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8
field public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; // 0x9
@@ -9187,6 +9189,7 @@
method @Nullable public String getDeviceProfile();
method @Nullable public CharSequence getDisplayName();
method public int getId();
+ method public int getSystemDataSyncFlags();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.companion.AssociationInfo> CREATOR;
}
@@ -9256,8 +9259,10 @@
method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.Callback);
method @Nullable public android.content.IntentSender buildAssociationCancellationIntent();
method @Nullable public android.content.IntentSender buildPermissionTransferUserConsentIntent(int) throws android.companion.DeviceNotAssociatedException;
+ method public void disableSystemDataSync(int, int);
method @Deprecated public void disassociate(@NonNull String);
method public void disassociate(int);
+ method public void enableSystemDataSync(int, int);
method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public java.util.List<android.companion.AssociationInfo> getAllAssociations();
method @Deprecated @NonNull public java.util.List<java.lang.String> getAssociations();
method @NonNull public java.util.List<android.companion.AssociationInfo> getMyAssociations();
@@ -9268,6 +9273,7 @@
method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION";
field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+ field public static final int FLAG_CALL_METADATA = 1; // 0x1
field public static final int RESULT_CANCELED = 0; // 0x0
field public static final int RESULT_DISCOVERY_TIMEOUT = 2; // 0x2
field public static final int RESULT_INTERNAL_ERROR = 3; // 0x3
@@ -12723,7 +12729,6 @@
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CAMERA}, anyOf={android.Manifest.permission.CAMERA}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR, android.Manifest.permission.UWB_RANGING}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10
field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1
- field @RequiresPermission(android.Manifest.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT) public static final int FOREGROUND_SERVICE_TYPE_FILE_MANAGEMENT = 4096; // 0x1000
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_HEALTH}, anyOf={android.Manifest.permission.ACTIVITY_RECOGNITION, android.Manifest.permission.BODY_SENSORS, android.Manifest.permission.HIGH_SAMPLING_RATE_SENSORS}) public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 256; // 0x100
field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_LOCATION}, anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8
field public static final int FOREGROUND_SERVICE_TYPE_MANIFEST = -1; // 0xffffffff
@@ -13023,9 +13028,9 @@
field @NonNull public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
field public static final int FONT_WEIGHT_ADJUSTMENT_UNDEFINED = 2147483647; // 0x7fffffff
- field public static final int GRAMMATICAL_GENDER_FEMININE = 3; // 0x3
- field public static final int GRAMMATICAL_GENDER_MASCULINE = 4; // 0x4
- field public static final int GRAMMATICAL_GENDER_NEUTRAL = 2; // 0x2
+ field public static final int GRAMMATICAL_GENDER_FEMININE = 2; // 0x2
+ field public static final int GRAMMATICAL_GENDER_MASCULINE = 3; // 0x3
+ field public static final int GRAMMATICAL_GENDER_NEUTRAL = 1; // 0x1
field public static final int GRAMMATICAL_GENDER_NOT_SPECIFIED = 0; // 0x0
field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
field public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0; // 0x0
@@ -13316,7 +13321,7 @@
method @NonNull public android.os.Bundle getCandidateQueryData();
method @NonNull public android.os.Bundle getCredentialData();
method @NonNull public String getType();
- method public boolean requireSystemProvider();
+ method public boolean isSystemProviderRequired();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CreateCredentialRequest> CREATOR;
}
@@ -13341,8 +13346,8 @@
public final class CredentialManager {
method public void clearCredentialState(@NonNull android.credentials.ClearCredentialStateRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
- method public void executeCreateCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
- method public void executeGetCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
+ method public void createCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
+ method public void getCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
}
public class GetCredentialException extends java.lang.Exception {
@@ -13363,7 +13368,7 @@
method @NonNull public android.os.Bundle getCandidateQueryData();
method @NonNull public android.os.Bundle getCredentialRetrievalData();
method @NonNull public String getType();
- method public boolean requireSystemProvider();
+ method public boolean isSystemProviderRequired();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialOption> CREATOR;
}
@@ -16334,7 +16339,10 @@
public class YuvImage {
ctor public YuvImage(byte[], int, int, int, int[]);
+ ctor public YuvImage(@NonNull byte[], int, int, int, @Nullable int[], @NonNull android.graphics.ColorSpace);
method public boolean compressToJpeg(android.graphics.Rect, int, java.io.OutputStream);
+ method public boolean compressToJpegR(@NonNull android.graphics.YuvImage, int, @NonNull java.io.OutputStream);
+ method @NonNull public android.graphics.ColorSpace getColorSpace();
method public int getHeight();
method public int[] getStrides();
method public int getWidth();
@@ -19273,10 +19281,20 @@
package android.hardware.input {
+ public final class HostUsiVersion implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMajorVersion();
+ method public int getMinorVersion();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.HostUsiVersion> CREATOR;
+ }
+
public final class InputManager {
+ method @Nullable public android.hardware.input.HostUsiVersion getHostUsiVersion(@NonNull android.view.Display);
method @Nullable public android.view.InputDevice getInputDevice(int);
method public int[] getInputDeviceIds();
method @FloatRange(from=0, to=1) public float getMaximumObscuringOpacityForTouch();
+ method public boolean isStylusPointerIconEnabled();
method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler);
method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener);
method @Nullable public android.view.VerifiedInputEvent verifyInputEvent(@NonNull android.view.InputEvent);
@@ -24046,6 +24064,7 @@
method @Nullable public android.os.Bundle getControlHints();
method @NonNull public java.util.List<android.media.MediaRoute2Info> getDeselectableRoutes();
method @NonNull public String getId();
+ method @NonNull public android.media.RoutingSessionInfo getRoutingSessionInfo();
method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectableRoutes();
method @NonNull public java.util.List<android.media.MediaRoute2Info> getSelectedRoutes();
method public int getVolume();
@@ -28395,15 +28414,24 @@
public final class NfcAdapter {
method public void disableForegroundDispatch(android.app.Activity);
+ method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
method public void disableReaderMode(android.app.Activity);
method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
+ method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
+ method @Deprecated public boolean invokeBeam(android.app.Activity);
method public boolean isEnabled();
+ method @Deprecated public boolean isNdefPushEnabled();
method public boolean isSecureNfcEnabled();
method public boolean isSecureNfcSupported();
+ method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
+ method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
+ method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
+ method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
@@ -28435,6 +28463,18 @@
field public static final int STATE_TURNING_ON = 2; // 0x2
}
+ @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
+ method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
+ method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
+ }
+
+ @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
+ method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent);
+ }
+
public static interface NfcAdapter.OnTagRemovedListener {
method public void onTagRemoved();
}
@@ -40427,17 +40467,24 @@
method @NonNull public String getCardId();
method @NonNull public android.graphics.drawable.Icon getCardImage();
method @Nullable public CharSequence getCardLabel();
+ method @NonNull public int getCardType();
method @NonNull public CharSequence getContentDescription();
method @NonNull public android.app.PendingIntent getPendingIntent();
+ method @Nullable public android.graphics.drawable.Icon getValuableCardSecondaryImage();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CARD_TYPE_PAYMENT = 1; // 0x1
+ field public static final int CARD_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int CARD_TYPE_VALUABLE = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.service.quickaccesswallet.WalletCard> CREATOR;
}
public static final class WalletCard.Builder {
+ ctor public WalletCard.Builder(@NonNull String, @NonNull int, @NonNull android.graphics.drawable.Icon, @NonNull CharSequence, @NonNull android.app.PendingIntent);
ctor public WalletCard.Builder(@NonNull String, @NonNull android.graphics.drawable.Icon, @NonNull CharSequence, @NonNull android.app.PendingIntent);
method @NonNull public android.service.quickaccesswallet.WalletCard build();
method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardIcon(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setCardLabel(@Nullable CharSequence);
+ method @NonNull public android.service.quickaccesswallet.WalletCard.Builder setValuableCardSecondaryImage(@Nullable android.graphics.drawable.Icon);
}
public final class WalletServiceEvent implements android.os.Parcelable {
@@ -40558,7 +40605,6 @@
method public void setDisabledShowContext(int);
method public final void setUiHints(@NonNull android.os.Bundle);
method public void showSession(android.os.Bundle, int);
- field public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
field public static final String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final String SERVICE_META_DATA = "android.voice_interaction";
}
@@ -40619,6 +40665,7 @@
method public void startAssistantActivity(android.content.Intent);
method public void startVoiceActivity(android.content.Intent);
method public final void unregisterVisibleActivityCallback(@NonNull android.service.voice.VoiceInteractionSession.VisibleActivityCallback);
+ field public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
@@ -41357,8 +41404,7 @@
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
}
- public final class CallControl implements java.lang.AutoCloseable {
- method public void close();
+ public final class CallControl {
method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method @NonNull public android.os.ParcelUuid getCallId();
method public void rejectCall(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -41607,6 +41653,7 @@
method public void onUsingAlternativeUi(boolean);
method public static String propertiesToString(int);
method public final void putExtras(@NonNull android.os.Bundle);
+ method public final void queryLocationForEmergency(@IntRange(from=100, to=5000) long, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.location.Location,android.telecom.QueryLocationException>);
method public final void removeExtras(java.util.List<java.lang.String>);
method public final void removeExtras(java.lang.String...);
method @Deprecated public void requestBluetoothAudio(@NonNull android.bluetooth.BluetoothDevice);
@@ -42010,6 +42057,22 @@
field public static final int REASON_USER_SET = 3; // 0x3
}
+ public final class QueryLocationException extends java.lang.RuntimeException implements android.os.Parcelable {
+ ctor public QueryLocationException(@Nullable String);
+ ctor public QueryLocationException(@Nullable String, int);
+ ctor public QueryLocationException(@Nullable String, int, @Nullable Throwable);
+ method public int describeContents();
+ method public int getCode();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telecom.QueryLocationException> CREATOR;
+ field public static final int ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS = 4; // 0x4
+ field public static final int ERROR_NOT_PERMITTED = 3; // 0x3
+ field public static final int ERROR_PREVIOUS_REQUEST_EXISTS = 2; // 0x2
+ field public static final int ERROR_REQUEST_TIME_OUT = 1; // 0x1
+ field public static final int ERROR_SERVICE_UNAVAILABLE = 5; // 0x5
+ field public static final int ERROR_UNSPECIFIED = 6; // 0x6
+ }
+
public final class RemoteConference {
method public void disconnect();
method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections();
@@ -42989,7 +43052,7 @@
field public static final String KEY_SMS_MAX_RETRY_COUNT_INT = "imssms.sms_max_retry_count_int";
field public static final String KEY_SMS_MAX_RETRY_COUNT_OVER_IMS_INT = "imssms.sms_max_retry_count_over_ims_int";
field public static final String KEY_SMS_OVER_IMS_FORMAT_INT = "imssms.sms_over_ims_format_int";
- field public static final String KEY_SMS_OVER_IMS_SEND_RETRY_DELAY_MILLIS_INT = "imssms.sms_rover_ims_send_retry_delay_millis_int";
+ field public static final String KEY_SMS_OVER_IMS_SEND_RETRY_DELAY_MILLIS_INT = "imssms.sms_over_ims_send_retry_delay_millis_int";
field public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL = "imssms.sms_over_ims_supported_bool";
field public static final String KEY_SMS_OVER_IMS_SUPPORTED_RATS_INT_ARRAY = "imssms.sms_over_ims_supported_rats_int_array";
field public static final String KEY_SMS_RP_CAUSE_VALUES_TO_FALLBACK_INT_ARRAY = "imssms.sms_rp_cause_values_to_fallback_int_array";
@@ -44843,6 +44906,7 @@
method public int getCardIdForDefaultEuicc();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
method public int getCarrierIdFromSimMccMnc();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void getCarrierRestrictionStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public int getDataNetworkType();
@@ -45002,6 +45066,10 @@
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
field public static final String CAPABILITY_SLICING_CONFIG_SUPPORTED = "CAPABILITY_SLICING_CONFIG_SUPPORTED";
+ field public static final int CARRIER_RESTRICTION_STATUS_NOT_RESTRICTED = 1; // 0x1
+ field public static final int CARRIER_RESTRICTION_STATUS_RESTRICTED = 2; // 0x2
+ field public static final int CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER = 3; // 0x3
+ field public static final int CARRIER_RESTRICTION_STATUS_UNKNOWN = 0; // 0x0
field public static final int CDMA_ROAMING_MODE_AFFILIATED = 1; // 0x1
field public static final int CDMA_ROAMING_MODE_ANY = 2; // 0x2
field public static final int CDMA_ROAMING_MODE_HOME = 0; // 0x0
@@ -46003,6 +46071,7 @@
field public static final int METHOD_PUBLISH = 2; // 0x2
field public static final int METHOD_REGISTER = 1; // 0x1
field public static final int METHOD_SUBSCRIBE = 3; // 0x3
+ field public static final int METHOD_UNKNOWN = 0; // 0x0
}
}
@@ -49327,6 +49396,7 @@
method @Nullable public android.view.SurfaceControl.Transaction buildReparentTransaction(@NonNull android.view.SurfaceControl);
method public default int getBufferTransformHint();
method public default void removeOnBufferTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnBufferTransformHintChangedListener);
+ method public default void setChildBoundingInsets(@NonNull android.graphics.Rect);
method public default void setTouchableRegion(@Nullable android.graphics.Region);
}
@@ -50772,6 +50842,7 @@
field public static final int TYPE_GRAB = 1020; // 0x3fc
field public static final int TYPE_GRABBING = 1021; // 0x3fd
field public static final int TYPE_HAND = 1002; // 0x3ea
+ field public static final int TYPE_HANDWRITING = 1022; // 0x3fe
field public static final int TYPE_HELP = 1003; // 0x3eb
field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
field public static final int TYPE_NO_DROP = 1012; // 0x3f4
@@ -50990,6 +51061,7 @@
method public void relayout(int, int);
method public void release();
method public void setView(@NonNull android.view.View, int, int);
+ method public boolean transferTouchGestureToHost();
}
public static final class SurfaceControlViewHost.SurfacePackage implements android.os.Parcelable {
@@ -54224,6 +54296,7 @@
method public void notifyViewExited(@NonNull android.view.View, int);
method public void notifyViewVisibilityChanged(@NonNull android.view.View, boolean);
method public void notifyViewVisibilityChanged(@NonNull android.view.View, int, boolean);
+ method public void notifyVirtualViewsReady(@NonNull android.view.View, @NonNull android.util.SparseArray<android.view.autofill.VirtualViewFillInfo>);
method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
method public void requestAutofill(@NonNull android.view.View);
method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect);
@@ -54270,6 +54343,16 @@
field @NonNull public static final android.os.Parcelable.Creator<android.view.autofill.AutofillValue> CREATOR;
}
+ public final class VirtualViewFillInfo {
+ method @Nullable public String[] getAutofillHints();
+ }
+
+ public static final class VirtualViewFillInfo.Builder {
+ ctor public VirtualViewFillInfo.Builder();
+ method @NonNull public android.view.autofill.VirtualViewFillInfo build();
+ method @NonNull public android.view.autofill.VirtualViewFillInfo.Builder setAutofillHints(@NonNull java.lang.String...);
+ }
+
}
package android.view.contentcapture {
@@ -54996,6 +55079,22 @@
method @NonNull public android.view.inputmethod.InsertGesture.Builder setTextToInsert(@NonNull String);
}
+ public final class InsertModeGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.os.CancellationSignal getCancellationSignal();
+ method @NonNull public android.graphics.PointF getInsertionPoint();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.InsertModeGesture> CREATOR;
+ }
+
+ public static final class InsertModeGesture.Builder {
+ ctor public InsertModeGesture.Builder();
+ method @NonNull public android.view.inputmethod.InsertModeGesture build();
+ method @NonNull public android.view.inputmethod.InsertModeGesture.Builder setCancellationSignal(@NonNull android.os.CancellationSignal);
+ method @NonNull public android.view.inputmethod.InsertModeGesture.Builder setFallbackText(@Nullable String);
+ method @NonNull public android.view.inputmethod.InsertModeGesture.Builder setInsertionPoint(@NonNull android.graphics.PointF);
+ }
+
public final class JoinOrSplitGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.graphics.PointF getJoinOrSplitPoint();
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 55ef6de..af35d96 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -83,7 +83,7 @@
public abstract class Context {
method @NonNull public android.content.Context createContextForSdkInSandbox(@NonNull android.content.pm.ApplicationInfo, int) throws android.content.pm.PackageManager.NameNotFoundException;
- method @NonNull public android.os.IBinder getIApplicationThreadBinder();
+ method @NonNull public android.os.IBinder getProcessToken();
method @NonNull public android.os.UserHandle getUser();
field public static final String PAC_PROXY_SERVICE = "pac_proxy";
field public static final String TEST_NETWORK_SERVICE = "test_network";
diff --git a/core/api/removed.txt b/core/api/removed.txt
index 5c4fd10..1fa1e89 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -252,34 +252,6 @@
}
-package android.nfc {
-
- public final class NfcAdapter {
- method @Deprecated public void disableForegroundNdefPush(android.app.Activity);
- method @Deprecated public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
- method @Deprecated public boolean invokeBeam(android.app.Activity);
- method @Deprecated public boolean isNdefPushEnabled();
- method @Deprecated public void setBeamPushUris(android.net.Uri[], android.app.Activity);
- method @Deprecated public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
- method @Deprecated public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
- method @Deprecated public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
- }
-
- @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
- method public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
- method public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
- }
-
- @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
- method public void onNdefPushComplete(android.nfc.NfcEvent);
- }
-
-}
-
package android.os {
public class BatteryManager {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e5b55b2..d3775ad 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -91,6 +91,7 @@
field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED";
field public static final String CAMERA_OPEN_CLOSE_LISTENER = "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD";
+ field public static final String CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD = "android.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD";
field public static final String CAPTURE_MEDIA_OUTPUT = "android.permission.CAPTURE_MEDIA_OUTPUT";
field public static final String CAPTURE_TUNER_AUDIO_INPUT = "android.permission.CAPTURE_TUNER_AUDIO_INPUT";
field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT";
@@ -248,6 +249,7 @@
field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
field public static final String PROVISION_DEMO_DEVICE = "android.permission.PROVISION_DEMO_DEVICE";
field public static final String QUERY_ADMIN_POLICY = "android.permission.QUERY_ADMIN_POLICY";
+ field public static final String QUERY_CLONED_APPS = "android.permission.QUERY_CLONED_APPS";
field @Deprecated public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
field public static final String QUERY_USERS = "android.permission.QUERY_USERS";
field public static final String RADIO_SCAN_WITHOUT_LOCATION = "android.permission.RADIO_SCAN_WITHOUT_LOCATION";
@@ -542,8 +544,8 @@
public class AlarmManager {
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, @NonNull android.app.PendingIntent, @Nullable android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, @NonNull android.app.AlarmManager.OnAlarmListener, @Nullable android.os.Handler, @Nullable android.os.WorkSource);
- method @RequiresPermission(allOf={android.Manifest.permission.UPDATE_DEVICE_STATS, android.Manifest.permission.SCHEDULE_EXACT_ALARM}, conditional=true) public void setExact(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @NonNull android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
- method @RequiresPermission(allOf={android.Manifest.permission.UPDATE_DEVICE_STATS, android.Manifest.permission.SCHEDULE_EXACT_ALARM}, conditional=true) public void setExactAndAllowWhileIdle(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @Nullable android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void setExact(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @NonNull android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void setExactAndAllowWhileIdle(int, long, @Nullable String, @NonNull java.util.concurrent.Executor, @Nullable android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
method @RequiresPermission(android.Manifest.permission.SCHEDULE_PRIORITIZED_ALARM) public void setPrioritized(int, long, long, @Nullable String, @NonNull java.util.concurrent.Executor, @NonNull android.app.AlarmManager.OnAlarmListener);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void setWindow(int, long, long, @Nullable String, @NonNull java.util.concurrent.Executor, @Nullable android.os.WorkSource, @NonNull android.app.AlarmManager.OnAlarmListener);
}
@@ -581,6 +583,7 @@
field public static final String OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER = "android:auto_revoke_managed_by_installer";
field public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = "android:auto_revoke_permissions_if_unused";
field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
+ field public static final String OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD = "android:capture_consentless_bugreport_on_userdebug_build";
field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
field public static final String OPSTR_ESTABLISH_VPN_MANAGER = "android:establish_vpn_manager";
field public static final String OPSTR_ESTABLISH_VPN_SERVICE = "android:establish_vpn_service";
@@ -1275,6 +1278,7 @@
field public static final int STATUS_DEVICE_ADMIN_NOT_SUPPORTED = 13; // 0xd
field public static final int STATUS_HAS_DEVICE_OWNER = 1; // 0x1
field public static final int STATUS_HAS_PAIRED = 8; // 0x8
+ field public static final int STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED = 16; // 0x10
field public static final int STATUS_MANAGED_USERS_NOT_SUPPORTED = 9; // 0x9
field public static final int STATUS_NONSYSTEM_USER_EXISTS = 5; // 0x5
field public static final int STATUS_NOT_SYSTEM_USER = 7; // 0x7
@@ -1522,6 +1526,7 @@
method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAncestralSerialNumber(long);
method @RequiresPermission(android.Manifest.permission.BACKUP) public void setAutoRestore(boolean);
method @RequiresPermission(android.Manifest.permission.BACKUP) public void setBackupEnabled(boolean);
+ method @RequiresPermission(allOf={android.Manifest.permission.BACKUP, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public void setFrameworkSchedulingEnabled(boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable String);
method @RequiresPermission(android.Manifest.permission.BACKUP) public void updateTransportAttributes(@NonNull android.content.ComponentName, @NonNull String, @Nullable android.content.Intent, @NonNull String, @Nullable android.content.Intent, @Nullable CharSequence);
field public static final int ERROR_AGENT_FAILURE = -1003; // 0xfffffc15
@@ -3006,8 +3011,13 @@
method public void onIntentIntercepted(@NonNull android.content.Intent);
}
+ public static interface VirtualDeviceManager.SoundEffectListener {
+ method public void onPlaySoundEffect(int);
+ }
+
public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
method public void addActivityListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
+ method public void addSoundEffectListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
method @NonNull public android.content.Context createContext();
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
@@ -3026,6 +3036,7 @@
method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
+ method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setShowPointerIcon(boolean);
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void unregisterIntentInterceptor(@NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
}
@@ -3259,6 +3270,7 @@
field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
field public static final String TETHERING_SERVICE = "tethering";
+ field public static final String TIME_MANAGER_SERVICE = "time_manager";
field public static final String TRANSLATION_MANAGER_SERVICE = "translation";
field public static final String UI_TRANSLATION_SERVICE = "ui_translation";
field public static final String UWB_SERVICE = "uwb";
@@ -3792,6 +3804,7 @@
field @Deprecated public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field @Deprecated public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ANY_USER = 4194304; // 0x400000
+ field public static final int MATCH_CLONE_PROFILE = 536870912; // 0x20000000
field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
field public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 536870912; // 0x20000000
field public static final int MATCH_INSTANT = 8388608; // 0x800000
@@ -9681,14 +9694,24 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
+ method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
+ method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
+ field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
+ field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
+ field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
+ field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe
}
public static interface NfcAdapter.ControllerAlwaysOnListener {
@@ -10036,6 +10059,7 @@
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
method public void unregisterSection(int);
+ field public static final int FLAG_ALLOW_CONSENTLESS_BUGREPORT = 2; // 0x2
field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
@@ -15674,6 +15698,7 @@
field public static final String SERVICE_ID_POST_CALL = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callunanswered";
field public static final String SERVICE_ID_SHARED_MAP = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.sharedmap";
field public static final String SERVICE_ID_SHARED_SKETCH = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.sharedsketch";
+ field public static final String SERVICE_ID_SLM = "org.openmobilealliance:StandaloneMsg";
field public static final String TUPLE_BASIC_STATUS_CLOSED = "closed";
field public static final String TUPLE_BASIC_STATUS_OPEN = "open";
}
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 1c10356..2c5acf1 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -140,17 +140,6 @@
}
-package android.nfc {
-
- public final class NfcAdapter {
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
- method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
- field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
- }
-
-}
-
package android.os {
public class Build {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 8c64e40..3a6173c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -908,8 +908,6 @@
method public boolean isProfile();
method public boolean isQuietModeEnabled();
method public boolean isRestricted();
- method public boolean isSystemOnly();
- method public static boolean isSystemOnly(int);
method public boolean supportsSwitchTo();
method public boolean supportsSwitchToByUser();
method public void writeToParcel(android.os.Parcel, int);
@@ -1416,6 +1414,8 @@
package android.hardware.location {
public final class ContextHubManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public boolean disableTestMode();
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public boolean enableTestMode();
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public long[] getPreloadedNanoAppIds(@NonNull android.hardware.location.ContextHubInfo);
}
@@ -1629,20 +1629,27 @@
public class AudioManager {
method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int abandonAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void forceComputeCsdOnAllDevices(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void forceUseFrameworkMel(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioRecord getCallDownlinkExtractionAudioRecord(@NonNull android.media.AudioFormat);
method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioTrack getCallUplinkInjectionAudioTrack(@NonNull android.media.AudioFormat);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public float getCsd();
method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int);
method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFadeOutDurationOnFocusLossMillis(@NonNull android.media.AudioAttributes);
method @Nullable public static android.media.AudioHalVersionInfo getHalVersion();
method public static final int[] getPublicStreamTypes();
method @NonNull public java.util.List<java.lang.Integer> getReportedSurroundFormats();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public float getRs2Value();
method public int getStreamMinVolumeInt(int);
method @NonNull public java.util.Map<java.lang.Integer,java.lang.Boolean> getSurroundFormats();
method public boolean hasRegisteredDynamicPolicy();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public boolean isCsdEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.QUERY_AUDIO_STATE}) public boolean isFullVolumeDevice();
method @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public boolean isPstnCallAudioInterceptable();
method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int requestAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String, int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void setCsd(float);
method public void setRampingRingerEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS) public void setRs2Value(float);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
}
@@ -2032,7 +2039,6 @@
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.List<android.content.pm.UserInfo> getUsers(boolean, boolean, boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean hasBaseUserRestriction(@NonNull String, @NonNull android.os.UserHandle);
- method public static boolean isSplitSystemUser();
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean isUserTypeEnabled(@NonNull String);
method public boolean isVisibleBackgroundUsersSupported();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo preCreateUser(@NonNull String) throws android.os.UserManager.UserOperationException;
@@ -2564,6 +2570,7 @@
public abstract class DreamOverlayService extends android.app.Service {
ctor public DreamOverlayService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public void onEndDream();
method public abstract void onStartDream(@NonNull android.view.WindowManager.LayoutParams);
method public final void requestExit();
method public final boolean shouldShowComplications();
@@ -2796,6 +2803,7 @@
field public static final int HAL_SERVICE_MESSAGING = 2; // 0x2
field public static final int HAL_SERVICE_MODEM = 3; // 0x3
field public static final int HAL_SERVICE_NETWORK = 4; // 0x4
+ field public static final int HAL_SERVICE_SATELLITE = 8; // 0x8
field public static final int HAL_SERVICE_SIM = 5; // 0x5
field public static final int HAL_SERVICE_VOICE = 6; // 0x6
field public static final android.util.Pair HAL_VERSION_UNKNOWN;
@@ -3338,6 +3346,7 @@
field public static final int GESTURE_TYPE_DELETE = 4; // 0x4
field public static final int GESTURE_TYPE_DELETE_RANGE = 64; // 0x40
field public static final int GESTURE_TYPE_INSERT = 2; // 0x2
+ field public static final int GESTURE_TYPE_INSERT_MODE = 128; // 0x80
field public static final int GESTURE_TYPE_JOIN_OR_SPLIT = 16; // 0x10
field public static final int GESTURE_TYPE_NONE = 0; // 0x0
field public static final int GESTURE_TYPE_REMOVE_SPACE = 8; // 0x8
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index a9d14df..a81ef18 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -23,6 +23,7 @@
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
import android.os.Build;
+import android.util.LongArray;
import java.util.ArrayList;
@@ -546,7 +547,6 @@
*/
void skipToEndValue(boolean inReverse) {}
-
/**
* Internal use only.
*
@@ -559,9 +559,36 @@
}
/**
- * Internal use only.
+ * Internal use only. Changes the value of the animator as if currentPlayTime has passed since
+ * the start of the animation. Therefore, currentPlayTime includes the start delay, and any
+ * repetition. lastPlayTime is similar and is used to calculate how many repeats have been
+ * done between the two times.
*/
- void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {}
+ void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {}
+
+ /**
+ * Internal use only. This animates any animation that has ended since lastPlayTime.
+ * If an animation hasn't been finished, no change will be made.
+ */
+ void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {}
+
+ /**
+ * Internal use only. Adds all start times (after delay) to and end times to times.
+ * The value must include offset.
+ */
+ void getStartAndEndTimes(LongArray times, long offset) {
+ long startTime = offset + getStartDelay();
+ if (times.indexOf(startTime) < 0) {
+ times.add(startTime);
+ }
+ long duration = getTotalDuration();
+ if (duration != DURATION_INFINITE) {
+ long endTime = duration + offset;
+ if (times.indexOf(endTime) < 0) {
+ times.add(endTime);
+ }
+ }
+ }
/**
* <p>An animation listener receives notifications from an animation.
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index bc8db02..257adfe 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -23,9 +23,11 @@
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.LongArray;
import android.view.animation.Animation;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
@@ -181,6 +183,16 @@
*/
private long mPauseTime = -1;
+ /**
+ * The start and stop times of all descendant animators.
+ */
+ private long[] mChildStartAndStopTimes;
+
+ /**
+ * Tracks whether we've notified listeners of the onAnimationStart() event.
+ */
+ private boolean mStartListenersCalled;
+
// This is to work around a bug in b/34736819. This needs to be removed once app team
// fixes their side.
private AnimatorListenerAdapter mAnimationEndListener = new AnimatorListenerAdapter() {
@@ -729,14 +741,7 @@
startAnimation();
}
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationStart(this, inReverse);
- }
- }
+ notifyStartListeners(inReverse);
if (isEmptySet) {
// In the case of empty AnimatorSet, or 0 duration scale, we will trigger the
// onAnimationEnd() right away.
@@ -744,6 +749,32 @@
}
}
+ private void notifyStartListeners(boolean inReverse) {
+ if (mListeners != null && !mStartListenersCalled) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ AnimatorListener listener = tmpListeners.get(i);
+ listener.onAnimationStart(this, inReverse);
+ }
+ }
+ mStartListenersCalled = true;
+ }
+
+ private void notifyEndListeners(boolean inReverse) {
+ if (mListeners != null && mStartListenersCalled) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ AnimatorListener listener = tmpListeners.get(i);
+ listener.onAnimationEnd(this, inReverse);
+ }
+ }
+ mStartListenersCalled = false;
+ }
+
// Returns true if set is empty or contains nothing but animator sets with no start delay.
private static boolean isEmptySet(AnimatorSet set) {
if (set.getStartDelay() > 0) {
@@ -779,26 +810,25 @@
@Override
void skipToEndValue(boolean inReverse) {
- if (!isInitialized()) {
- throw new UnsupportedOperationException("Children must be initialized.");
- }
-
// This makes sure the animation events are sorted an up to date.
initAnimation();
+ initChildren();
// Calling skip to the end in the sequence that they would be called in a forward/reverse
// run, such that the sequential animations modifying the same property would have
// the right value in the end.
if (inReverse) {
for (int i = mEvents.size() - 1; i >= 0; i--) {
- if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
- mEvents.get(i).mNode.mAnimation.skipToEndValue(true);
+ AnimationEvent event = mEvents.get(i);
+ if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+ event.mNode.mAnimation.skipToEndValue(true);
}
}
} else {
for (int i = 0; i < mEvents.size(); i++) {
- if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_END) {
- mEvents.get(i).mNode.mAnimation.skipToEndValue(false);
+ AnimationEvent event = mEvents.get(i);
+ if (event.mEvent == AnimationEvent.ANIMATION_END) {
+ event.mNode.mAnimation.skipToEndValue(false);
}
}
}
@@ -814,72 +844,216 @@
* {@link android.view.animation.Animation.AnimationListener#onAnimationRepeat(Animation)},
* as needed, based on the last play time and current play time.
*/
- @Override
- void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
- if (currentPlayTime < 0 || lastPlayTime < 0) {
+ private void animateBasedOnPlayTime(
+ long currentPlayTime,
+ long lastPlayTime,
+ boolean inReverse,
+ boolean notify
+ ) {
+ if (currentPlayTime < 0 || lastPlayTime < -1) {
throw new UnsupportedOperationException("Error: Play time should never be negative.");
}
// TODO: take into account repeat counts and repeat callback when repeat is implemented.
- // Clamp currentPlayTime and lastPlayTime
- // TODO: Make this more efficient
-
- // Convert the play times to the forward direction.
if (inReverse) {
- if (getTotalDuration() == DURATION_INFINITE) {
- throw new UnsupportedOperationException("Cannot reverse AnimatorSet with infinite"
- + " duration");
+ long duration = getTotalDuration();
+ if (duration == DURATION_INFINITE) {
+ throw new UnsupportedOperationException(
+ "Cannot reverse AnimatorSet with infinite duration"
+ );
}
- long duration = getTotalDuration() - mStartDelay;
+ // Convert the play times to the forward direction.
currentPlayTime = Math.min(currentPlayTime, duration);
currentPlayTime = duration - currentPlayTime;
lastPlayTime = duration - lastPlayTime;
- inReverse = false;
}
- ArrayList<Node> unfinishedNodes = new ArrayList<>();
- // Assumes forward playing from here on.
- for (int i = 0; i < mEvents.size(); i++) {
- AnimationEvent event = mEvents.get(i);
- if (event.getTime() > currentPlayTime || event.getTime() == DURATION_INFINITE) {
- break;
- }
+ long[] startEndTimes = ensureChildStartAndEndTimes();
+ int index = findNextIndex(lastPlayTime, startEndTimes);
+ int endIndex = findNextIndex(currentPlayTime, startEndTimes);
- // This animation started prior to the current play time, and won't finish before the
- // play time, add to the unfinished list.
- if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
- if (event.mNode.mEndTime == DURATION_INFINITE
- || event.mNode.mEndTime > currentPlayTime) {
- unfinishedNodes.add(event.mNode);
+ // Change values at the start/end times so that values are set in the right order.
+ // We don't want an animator that would finish before another to override the value
+ // set by another animator that finishes earlier.
+ if (currentPlayTime >= lastPlayTime) {
+ while (index < endIndex) {
+ long playTime = startEndTimes[index];
+ if (lastPlayTime != playTime) {
+ animateSkipToEnds(playTime, lastPlayTime, notify);
+ animateValuesInRange(playTime, lastPlayTime, notify);
+ lastPlayTime = playTime;
+ }
+ index++;
+ }
+ } else {
+ while (index > endIndex) {
+ index--;
+ long playTime = startEndTimes[index];
+ if (lastPlayTime != playTime) {
+ animateSkipToEnds(playTime, lastPlayTime, notify);
+ animateValuesInRange(playTime, lastPlayTime, notify);
+ lastPlayTime = playTime;
}
}
- // For animations that do finish before the play time, end them in the sequence that
- // they would in a normal run.
- if (event.mEvent == AnimationEvent.ANIMATION_END) {
- // Skip to the end of the animation.
- event.mNode.mAnimation.skipToEndValue(false);
+ }
+ if (currentPlayTime != lastPlayTime) {
+ animateSkipToEnds(currentPlayTime, lastPlayTime, notify);
+ animateValuesInRange(currentPlayTime, lastPlayTime, notify);
+ }
+ }
+
+ /**
+ * Looks through startEndTimes for playTime. If it is in startEndTimes, the index after
+ * is returned. Otherwise, it returns the index at which it would be placed if it were
+ * to be inserted.
+ */
+ private int findNextIndex(long playTime, long[] startEndTimes) {
+ int index = Arrays.binarySearch(startEndTimes, playTime);
+ if (index < 0) {
+ index = -index - 1;
+ } else {
+ index++;
+ }
+ return index;
+ }
+
+ @Override
+ void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
+ initAnimation();
+
+ if (lastPlayTime > currentPlayTime) {
+ if (notify) {
+ notifyStartListeners(true);
+ }
+ for (int i = mEvents.size() - 1; i >= 0; i--) {
+ AnimationEvent event = mEvents.get(i);
+ Node node = event.mNode;
+ if (event.mEvent == AnimationEvent.ANIMATION_END
+ && node.mStartTime != DURATION_INFINITE
+ ) {
+ Animator animator = node.mAnimation;
+ long start = node.mStartTime;
+ long end = node.mTotalDuration == DURATION_INFINITE
+ ? Long.MAX_VALUE : node.mEndTime;
+ if (currentPlayTime <= start && start < lastPlayTime) {
+ animator.animateSkipToEnds(
+ 0,
+ lastPlayTime - node.mStartTime,
+ notify
+ );
+ } else if (start <= currentPlayTime && currentPlayTime <= end) {
+ animator.animateSkipToEnds(
+ currentPlayTime - node.mStartTime,
+ lastPlayTime - node.mStartTime,
+ notify
+ );
+ }
+ }
+ }
+ if (currentPlayTime <= 0 && notify) {
+ notifyEndListeners(true);
+ }
+ } else {
+ if (notify) {
+ notifyStartListeners(false);
+ }
+ int eventsSize = mEvents.size();
+ for (int i = 0; i < eventsSize; i++) {
+ AnimationEvent event = mEvents.get(i);
+ Node node = event.mNode;
+ if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
+ && node.mStartTime != DURATION_INFINITE
+ ) {
+ Animator animator = node.mAnimation;
+ long start = node.mStartTime;
+ long end = node.mTotalDuration == DURATION_INFINITE
+ ? Long.MAX_VALUE : node.mEndTime;
+ if (lastPlayTime < end && end <= currentPlayTime) {
+ animator.animateSkipToEnds(
+ end - node.mStartTime,
+ lastPlayTime - node.mStartTime,
+ notify
+ );
+ } else if (start <= currentPlayTime && currentPlayTime <= end) {
+ animator.animateSkipToEnds(
+ currentPlayTime - node.mStartTime,
+ lastPlayTime - node.mStartTime,
+ notify
+ );
+ }
+ }
+ }
+ if (currentPlayTime >= getTotalDuration() && notify) {
+ notifyEndListeners(false);
+ }
+ }
+ }
+
+ @Override
+ void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
+ initAnimation();
+
+ if (notify) {
+ if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
+ notifyStartListeners(false);
+ } else {
+ long duration = getTotalDuration();
+ if (duration >= 0
+ && (lastPlayTime > duration || (lastPlayTime == duration
+ && currentPlayTime < duration))
+ ) {
+ notifyStartListeners(true);
+ }
}
}
- // Seek unfinished animation to the right time.
- for (int i = 0; i < unfinishedNodes.size(); i++) {
- Node node = unfinishedNodes.get(i);
- long playTime = getPlayTimeForNode(currentPlayTime, node, inReverse);
- if (!inReverse) {
- playTime -= node.mAnimation.getStartDelay();
- }
- node.mAnimation.animateBasedOnPlayTime(playTime, lastPlayTime, inReverse);
- }
-
- // Seek not yet started animations.
- for (int i = 0; i < mEvents.size(); i++) {
+ int eventsSize = mEvents.size();
+ for (int i = 0; i < eventsSize; i++) {
AnimationEvent event = mEvents.get(i);
- if (event.getTime() > currentPlayTime
- && event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
- event.mNode.mAnimation.skipToEndValue(true);
+ Node node = event.mNode;
+ if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
+ && node.mStartTime != DURATION_INFINITE
+ ) {
+ Animator animator = node.mAnimation;
+ long start = node.mStartTime;
+ long end = node.mTotalDuration == DURATION_INFINITE
+ ? Long.MAX_VALUE : node.mEndTime;
+ if ((start < currentPlayTime && currentPlayTime < end)
+ || (start == currentPlayTime && lastPlayTime < start)
+ || (end == currentPlayTime && lastPlayTime > end)
+ ) {
+ animator.animateValuesInRange(
+ currentPlayTime - node.mStartTime,
+ Math.max(-1, lastPlayTime - node.mStartTime),
+ notify
+ );
+ }
}
}
+ }
+ private long[] ensureChildStartAndEndTimes() {
+ if (mChildStartAndStopTimes == null) {
+ LongArray startAndEndTimes = new LongArray();
+ getStartAndEndTimes(startAndEndTimes, 0);
+ long[] times = startAndEndTimes.toArray();
+ Arrays.sort(times);
+ mChildStartAndStopTimes = times;
+ }
+ return mChildStartAndStopTimes;
+ }
+
+ @Override
+ void getStartAndEndTimes(LongArray times, long offset) {
+ int eventsSize = mEvents.size();
+ for (int i = 0; i < eventsSize; i++) {
+ AnimationEvent event = mEvents.get(i);
+ if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
+ && event.mNode.mStartTime != DURATION_INFINITE
+ ) {
+ event.mNode.mAnimation.getStartAndEndTimes(times, offset + event.mNode.mStartTime);
+ }
+ }
}
@Override
@@ -899,10 +1073,6 @@
return mChildrenInitialized;
}
- private void skipToStartValue(boolean inReverse) {
- skipToEndValue(!inReverse);
- }
-
/**
* Sets the position of the animation to the specified point in time. This time should
* be between 0 and the total duration of the animation, including any repetition. If
@@ -910,6 +1080,11 @@
* set to this time; it will simply set the time to this value and perform any appropriate
* actions based on that time. If the animation is already running, then setCurrentPlayTime()
* will set the current playing time to this value and continue playing from that point.
+ * On {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above, an AnimatorSet
+ * that hasn't been {@link #start()}ed, will issue
+ * {@link android.animation.Animator.AnimatorListener#onAnimationStart(Animator, boolean)}
+ * and {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator, boolean)}
+ * events.
*
* @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
* Unless the animation is reversing, the playtime is considered the time since
@@ -926,29 +1101,27 @@
if ((getTotalDuration() != DURATION_INFINITE && playTime > getTotalDuration() - mStartDelay)
|| playTime < 0) {
throw new UnsupportedOperationException("Error: Play time should always be in between"
- + "0 and duration.");
+ + " 0 and duration.");
}
initAnimation();
+ long lastPlayTime = mSeekState.getPlayTime();
if (!isStarted() || isPaused()) {
- if (mReversing) {
+ if (mReversing && !isStarted()) {
throw new UnsupportedOperationException("Error: Something went wrong. mReversing"
+ " should not be set when AnimatorSet is not started.");
}
if (!mSeekState.isActive()) {
findLatestEventIdForTime(0);
- // Set all the values to start values.
initChildren();
+ // Set all the values to start values.
+ skipToEndValue(!mReversing);
mSeekState.setPlayTime(0, mReversing);
}
- animateBasedOnPlayTime(playTime, 0, mReversing);
- mSeekState.setPlayTime(playTime, mReversing);
- } else {
- // If the animation is running, just set the seek time and wait until the next frame
- // (i.e. doAnimationFrame(...)) to advance the animation.
- mSeekState.setPlayTime(playTime, mReversing);
}
+ animateBasedOnPlayTime(playTime, lastPlayTime, mReversing, true);
+ mSeekState.setPlayTime(playTime, mReversing);
}
/**
@@ -981,10 +1154,16 @@
private void initChildren() {
if (!isInitialized()) {
mChildrenInitialized = true;
- // Forcefully initialize all children based on their end time, so that if the start
- // value of a child is dependent on a previous animation, the animation will be
- // initialized after the the previous animations have been advanced to the end.
- skipToEndValue(false);
+
+ // We have to initialize all the start values so that they are based on the previous
+ // values.
+ long[] times = ensureChildStartAndEndTimes();
+
+ long previousTime = -1;
+ for (long time : times) {
+ animateBasedOnPlayTime(time, previousTime, false, false);
+ previousTime = time;
+ }
}
}
@@ -1058,7 +1237,7 @@
for (int i = 0; i < mPlayingSet.size(); i++) {
Node node = mPlayingSet.get(i);
if (!node.mEnded) {
- pulseFrame(node, getPlayTimeForNode(unscaledPlayTime, node));
+ pulseFrame(node, getPlayTimeForNodeIncludingDelay(unscaledPlayTime, node));
}
}
@@ -1129,7 +1308,7 @@
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED && !node.mEnded) {
// end event:
- pulseFrame(node, getPlayTimeForNode(playTime, node));
+ pulseFrame(node, getPlayTimeForNodeIncludingDelay(playTime, node));
}
}
} else {
@@ -1150,7 +1329,7 @@
pulseFrame(node, 0);
} else if (event.mEvent == AnimationEvent.ANIMATION_END && !node.mEnded) {
// start event:
- pulseFrame(node, getPlayTimeForNode(playTime, node));
+ pulseFrame(node, getPlayTimeForNodeIncludingDelay(playTime, node));
}
}
}
@@ -1172,11 +1351,15 @@
}
}
- private long getPlayTimeForNode(long overallPlayTime, Node node) {
- return getPlayTimeForNode(overallPlayTime, node, mReversing);
+ private long getPlayTimeForNodeIncludingDelay(long overallPlayTime, Node node) {
+ return getPlayTimeForNodeIncludingDelay(overallPlayTime, node, mReversing);
}
- private long getPlayTimeForNode(long overallPlayTime, Node node, boolean inReverse) {
+ private long getPlayTimeForNodeIncludingDelay(
+ long overallPlayTime,
+ Node node,
+ boolean inReverse
+ ) {
if (inReverse) {
overallPlayTime = getTotalDuration() - overallPlayTime;
return node.mEndTime - overallPlayTime;
@@ -1198,26 +1381,8 @@
}
// Set the child animators to the right end:
if (mShouldResetValuesAtStart) {
- if (isInitialized()) {
- skipToEndValue(!mReversing);
- } else if (mReversing) {
- // Reversing but haven't initialized all the children yet.
- initChildren();
- skipToEndValue(!mReversing);
- } else {
- // If not all children are initialized and play direction is forward
- for (int i = mEvents.size() - 1; i >= 0; i--) {
- if (mEvents.get(i).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
- Animator anim = mEvents.get(i).mNode.mAnimation;
- // Only reset the animations that have been initialized to start value,
- // so that if they are defined without a start value, they will get the
- // values set at the right time (i.e. the next animation run)
- if (anim.isInitialized()) {
- anim.skipToEndValue(true);
- }
- }
- }
- }
+ initChildren();
+ skipToEndValue(!mReversing);
}
if (mReversing || mStartDelay == 0 || mSeekState.isActive()) {
@@ -1292,15 +1457,7 @@
// No longer receive callbacks
removeAnimationCallback();
- // Call end listener
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this, mReversing);
- }
- }
+ notifyEndListeners(mReversing);
removeAnimationEndListener();
mSelfPulse = true;
mReversing = false;
@@ -1922,11 +2079,11 @@
}
void setPlayTime(long playTime, boolean inReverse) {
- // TODO: This can be simplified.
-
// Clamp the play time
if (getTotalDuration() != DURATION_INFINITE) {
mPlayTime = Math.min(playTime, getTotalDuration() - mStartDelay);
+ } else {
+ mPlayTime = playTime;
}
mPlayTime = Math.max(0, mPlayTime);
mSeekingInReverse = inReverse;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 6ab7ae6..7009725 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -324,8 +324,9 @@
listenerCopy = new ArrayList<>(sDurationScaleChangeListeners);
}
- for (WeakReference<DurationScaleChangeListener> listenerRef : listenerCopy) {
- final DurationScaleChangeListener listener = listenerRef.get();
+ int listenersSize = listenerCopy.size();
+ for (int i = 0; i < listenersSize; i++) {
+ final DurationScaleChangeListener listener = listenerCopy.get(i).get();
if (listener != null) {
listener.onChanged(durationScale);
}
@@ -624,7 +625,7 @@
public void setValues(PropertyValuesHolder... values) {
int numValues = values.length;
mValues = values;
- mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
+ mValuesMap = new HashMap<>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = values[i];
mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
@@ -658,9 +659,11 @@
@CallSuper
void initAnimation() {
if (!mInitialized) {
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].init();
+ if (mValues != null) {
+ int numValues = mValues.length;
+ for (int i = 0; i < numValues; ++i) {
+ mValues[i].init();
+ }
}
mInitialized = true;
}
@@ -1105,18 +1108,30 @@
}
}
- private void notifyStartListeners() {
+ private void notifyStartListeners(boolean isReversing) {
if (mListeners != null && !mStartListenersCalled) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationStart(this, mReversing);
+ tmpListeners.get(i).onAnimationStart(this, isReversing);
}
}
mStartListenersCalled = true;
}
+ private void notifyEndListeners(boolean isReversing) {
+ if (mListeners != null && mStartListenersCalled) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationEnd(this, isReversing);
+ }
+ }
+ mStartListenersCalled = false;
+ }
+
/**
* Start the animation playing. This version of start() takes a boolean flag that indicates
* whether the animation should play in reverse. The flag is usually false, but may be set
@@ -1207,12 +1222,16 @@
if ((mStarted || mRunning) && mListeners != null) {
if (!mRunning) {
// If it's not yet running, then start listeners weren't called. Call them now.
- notifyStartListeners();
+ notifyStartListeners(mReversing);
}
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
+ int listenersSize = mListeners.size();
+ if (listenersSize > 0) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ for (int i = 0; i < listenersSize; i++) {
+ AnimatorListener listener = tmpListeners.get(i);
+ listener.onAnimationCancel(this);
+ }
}
}
endAnimation();
@@ -1317,22 +1336,14 @@
boolean notify = (mStarted || mRunning) && mListeners != null;
if (notify && !mRunning) {
// If it's not yet running, then start listeners weren't called. Call them now.
- notifyStartListeners();
+ notifyStartListeners(mReversing);
}
mRunning = false;
mStarted = false;
- mStartListenersCalled = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
- if (notify && mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this, mReversing);
- }
- }
+ notifyEndListeners(mReversing);
// mReversing needs to be reset *after* notifying the listeners for the end callbacks.
mReversing = false;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
@@ -1359,9 +1370,8 @@
} else {
mOverallFraction = 0f;
}
- if (mListeners != null) {
- notifyStartListeners();
- }
+
+ notifyStartListeners(mReversing);
}
/**
@@ -1452,16 +1462,32 @@
* will be called.
*/
@Override
- void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
- if (currentPlayTime < 0 || lastPlayTime < 0) {
+ void animateValuesInRange(long currentPlayTime, long lastPlayTime, boolean notify) {
+ if (currentPlayTime < 0 || lastPlayTime < -1) {
throw new UnsupportedOperationException("Error: Play time should never be negative.");
}
initAnimation();
+ long duration = getTotalDuration();
+ if (notify) {
+ if (lastPlayTime < 0 || (lastPlayTime == 0 && currentPlayTime > 0)) {
+ notifyStartListeners(false);
+ } else if (lastPlayTime > duration
+ || (lastPlayTime == duration && currentPlayTime < duration)
+ ) {
+ notifyStartListeners(true);
+ }
+ }
+ if (duration >= 0) {
+ lastPlayTime = Math.min(duration, lastPlayTime);
+ }
+ lastPlayTime -= mStartDelay;
+ currentPlayTime -= mStartDelay;
+
// Check whether repeat callback is needed only when repeat count is non-zero
if (mRepeatCount > 0) {
- int iteration = (int) (currentPlayTime / mDuration);
- int lastIteration = (int) (lastPlayTime / mDuration);
+ int iteration = Math.max(0, (int) (currentPlayTime / mDuration));
+ int lastIteration = Math.max(0, (int) (lastPlayTime / mDuration));
// Clamp iteration to [0, mRepeatCount]
iteration = Math.min(iteration, mRepeatCount);
@@ -1477,16 +1503,37 @@
}
}
- if (mRepeatCount != INFINITE && currentPlayTime >= (mRepeatCount + 1) * mDuration) {
- skipToEndValue(inReverse);
+ if (mRepeatCount != INFINITE && currentPlayTime > (mRepeatCount + 1) * mDuration) {
+ throw new IllegalStateException("Can't animate a value outside of the duration");
} else {
// Find the current fraction:
- float fraction = currentPlayTime / (float) mDuration;
- fraction = getCurrentIterationFraction(fraction, inReverse);
+ float fraction = Math.max(0, currentPlayTime) / (float) mDuration;
+ fraction = getCurrentIterationFraction(fraction, false);
animateValue(fraction);
}
}
+ @Override
+ void animateSkipToEnds(long currentPlayTime, long lastPlayTime, boolean notify) {
+ boolean inReverse = currentPlayTime < lastPlayTime;
+ boolean doSkip;
+ if (currentPlayTime <= 0 && lastPlayTime > 0) {
+ doSkip = true;
+ } else {
+ long duration = getTotalDuration();
+ doSkip = duration >= 0 && currentPlayTime >= duration && lastPlayTime < duration;
+ }
+ if (doSkip) {
+ if (notify) {
+ notifyStartListeners(inReverse);
+ }
+ skipToEndValue(inReverse);
+ if (notify) {
+ notifyEndListeners(inReverse);
+ }
+ }
+ }
+
/**
* Internal use only.
* Skips the animation value to end/start, depending on whether the play direction is forward
@@ -1641,6 +1688,9 @@
Trace.traceCounter(Trace.TRACE_TAG_VIEW, getNameForTrace() + hashCode(),
(int) (fraction * 1000));
}
+ if (mValues == null) {
+ return;
+ }
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index a14f3d3..84320ca 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1439,9 +1439,18 @@
public static final int OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON;
+ /**
+ * Allows an application to capture bugreport directly without consent dialog when using the
+ * bugreporting API on userdebug/eng build.
+ *
+ * @hide
+ */
+ public static final int OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD =
+ AppProtoEnums.APP_OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 131;
+ public static final int _NUM_OP = 132;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -2011,6 +2020,16 @@
public static final String OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON =
"android:system_exempt_from_fgs_stop_button";
+ /**
+ * Allows an application to capture bugreport directly without consent dialog when using the
+ * bugreporting API on userdebug/eng build.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD =
+ "android:capture_consentless_bugreport_on_userdebug_build";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2108,6 +2127,7 @@
OP_RUN_LONG_JOBS,
OP_READ_MEDIA_VISUAL_USER_SELECTED,
OP_FOREGROUND_SERVICE_SPECIAL_USE,
+ OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
};
static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
@@ -2515,7 +2535,13 @@
.build(),
new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
OPSTR_SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON,
- "SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON").build()
+ "SYSTEM_EXEMPT_FROM_FGS_STOP_BUTTON").build(),
+ new AppOpInfo.Builder(
+ OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
+ OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
+ "CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD")
+ .setPermission(Manifest.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD)
+ .build()
};
// The number of longs needed to form a full bitmask of app ops
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 9ecf8ff..88765c3 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -909,7 +909,6 @@
/**
* Clear the {@link BundleMerger} object that was previously set using
* {@link #setDeliveryGroupExtrasMerger(BundleMerger)}.
- *
* @hide
*/
public void clearDeliveryGroupExtrasMerger() {
@@ -917,6 +916,36 @@
}
/**
+ * Set PendingIntent activity is allowed to be started in the background if the caller
+ * can start background activities.
+ *
+ * @deprecated use #setPendingIntentBackgroundActivityStartMode(int) to set the full range
+ * of states
+ * @hide
+ */
+ @SystemApi
+ @Override
+ @Deprecated public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) {
+ super.setPendingIntentBackgroundActivityLaunchAllowed(allowed);
+ }
+
+ /**
+ * Get PendingIntent activity is allowed to be started in the background if the caller can start
+ * background activities.
+ *
+ * @deprecated use {@link #getPendingIntentBackgroundActivityStartMode()} since for apps
+ * targeting {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or higher this value might
+ * not match the actual behavior if the value was not explicitly set.
+ * @hide
+ */
+ @SystemApi
+ @Override
+ @Deprecated public boolean isPendingIntentBackgroundActivityLaunchAllowed() {
+ return super.isPendingIntentBackgroundActivityLaunchAllowed();
+ }
+
+
+ /**
* Sets the mode for allowing or denying the senders privileges to start background activities
* to the PendingIntent.
*
@@ -924,7 +953,6 @@
* methods. A privileged sender of a PendingIntent should only grant
* MODE_BACKGROUND_ACTIVITY_START_ALLOWED if the PendingIntent is from a trusted source and/or
* executed on behalf the user.
- *
* @hide
*/
@SystemApi
@@ -936,6 +964,19 @@
}
/**
+ * Gets the mode for allowing or denying the senders privileges to start background activities
+ * to the PendingIntent.
+ *
+ * @see #setPendingIntentBackgroundActivityStartMode(int)
+ * @hide
+ */
+ @SystemApi
+ @Override // to narrow down the return type
+ public @BackgroundActivityStartMode int getPendingIntentBackgroundActivityStartMode() {
+ return super.getPendingIntentBackgroundActivityStartMode();
+ }
+
+ /**
* Returns the created options as a Bundle, which can be passed to
* {@link android.content.Context#sendBroadcast(android.content.Intent)
* Context.sendBroadcast(Intent)} and related methods.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b91fa35..89740af 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2028,7 +2028,7 @@
/** @hide */
@NonNull
@Override
- public IBinder getIApplicationThreadBinder() {
+ public IBinder getProcessToken() {
return getIApplicationThread().asBinder();
}
diff --git a/core/java/android/app/DisabledWallpaperManager.java b/core/java/android/app/DisabledWallpaperManager.java
index fae6887..4a5836c 100644
--- a/core/java/android/app/DisabledWallpaperManager.java
+++ b/core/java/android/app/DisabledWallpaperManager.java
@@ -178,6 +178,11 @@
}
@Override
+ public ParcelFileDescriptor getWallpaperFile(int which, boolean getCropped) {
+ return unsupported();
+ }
+
+ @Override
public void forgetLoadedWallpaper() {
unsupported();
}
@@ -188,6 +193,11 @@
}
@Override
+ public ParcelFileDescriptor getWallpaperInfoFile() {
+ return unsupported();
+ }
+
+ @Override
public WallpaperInfo getWallpaperInfoForUser(int userId) {
return unsupported();
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index b1ed152..f4373a6 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -74,7 +74,8 @@
* Get the wallpaper for a given user.
*/
ParcelFileDescriptor getWallpaperWithFeature(String callingPkg, String callingFeatureId,
- IWallpaperManagerCallback cb, int which, out Bundle outParams, int userId);
+ IWallpaperManagerCallback cb, int which, out Bundle outParams, int userId,
+ boolean getCropped);
/**
* Retrieve the given user's current wallpaper ID of the given kind.
@@ -96,6 +97,12 @@
WallpaperInfo getWallpaperInfoWithFlags(int which, int userId);
/**
+ * Return a file descriptor for the file that contains metadata about the given user's
+ * wallpaper.
+ */
+ ParcelFileDescriptor getWallpaperInfoFile(int userId);
+
+ /**
* Clear the system wallpaper.
*/
void clearWallpaper(in String callingPackage, int which, int userId);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c081d82..9b348fc 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7947,8 +7947,6 @@
* @hide
*/
public MessagingStyle setShortcutIcon(@Nullable Icon conversationIcon) {
- // TODO(b/228941516): This icon should be downscaled to avoid using too much memory,
- // see reduceImageSizes.
mShortcutIcon = conversationIcon;
return this;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5b3b2a6..1f5182a 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1335,7 +1335,7 @@
return new TimeZoneDetectorImpl();
}});
- registerService(Context.TIME_MANAGER, TimeManager.class,
+ registerService(Context.TIME_MANAGER_SERVICE, TimeManager.class,
new CachedServiceFetcher<TimeManager>() {
@Override
public TimeManager createService(ContextImpl ctx)
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 1187459..f3a83d8 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -640,7 +640,7 @@
Bundle params = new Bundle();
try (ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
context.getOpPackageName(), context.getAttributionTag(), this, which,
- params, userId)) {
+ params, userId, /* getCropped = */ true)) {
// Let's peek user wallpaper first.
if (pfd != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
@@ -690,7 +690,7 @@
Bundle params = new Bundle();
ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
context.getOpPackageName(), context.getAttributionTag(), this, which,
- params, userId);
+ params, userId, /* getCropped = */ true);
if (pfd != null) {
try (BufferedInputStream bis = new BufferedInputStream(
@@ -1437,6 +1437,27 @@
*/
@UnsupportedAppUsage
public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, int userId) {
+ return getWallpaperFile(which, userId, /* getCropped = */ true);
+ }
+
+ /**
+ * Version of {@link #getWallpaperFile(int)} that allows specifying whether to get the
+ * cropped version of the wallpaper file or the original.
+ *
+ * @param which The wallpaper whose image file is to be retrieved. Must be a single
+ * defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}.
+ * @param getCropped If true the cropped file will be retrieved, if false the original will
+ * be retrieved.
+ *
+ * @hide
+ */
+ @Nullable
+ public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, boolean getCropped) {
+ return getWallpaperFile(which, mContext.getUserId(), getCropped);
+ }
+
+ private ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, int userId,
+ boolean getCropped) {
checkExactlyOneWallpaperFlagSet(which);
if (sGlobals.mService == null) {
@@ -1446,7 +1467,8 @@
try {
Bundle outParams = new Bundle();
return sGlobals.mService.getWallpaperWithFeature(mContext.getOpPackageName(),
- mContext.getAttributionTag(), null, which, outParams, userId);
+ mContext.getAttributionTag(), null, which, outParams,
+ userId, getCropped);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
@@ -1530,6 +1552,28 @@
}
/**
+ * Get an open, readable file descriptor for the file that contains metadata about the
+ * context user's wallpaper.
+ *
+ * The caller is responsible for closing the file descriptor when done ingesting the file.
+ *
+ * @hide
+ */
+ @Nullable
+ public ParcelFileDescriptor getWallpaperInfoFile() {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ throw new RuntimeException(new DeadSystemException());
+ } else {
+ try {
+ return sGlobals.mService.getWallpaperInfoFile(mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* Get the ID of the current wallpaper of the given kind. If there is no
* such wallpaper configured, returns a negative number.
*
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 67408a4..e4ee959 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -16,6 +16,7 @@
package android.app.admin;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -158,6 +159,24 @@
*/
public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
+
+ /**
+ * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should not
+ * be provisioned into Device Owner mode on a Headless System User Mode device.
+ */
+ public static final int HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED = 0;
+
+ /**
+ * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should be
+ * provisioned into "affiliated" mode when on a Headless System User Mode device.
+ *
+ * <p>This mode adds a Profile Owner to all users other than the user the Device Owner is on.
+ */
+ public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1;
+
+ @IntDef({HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED, HEADLESS_DEVICE_OWNER_MODE_AFFILIATED})
+ private @interface HeadlessDeviceOwnerMode {}
+
/** @hide */
public static class PolicyInfo {
public final int ident;
@@ -255,6 +274,8 @@
*/
boolean mSupportsTransferOwnership;
+ @HeadlessDeviceOwnerMode int mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
+
/**
* Constructor.
*
@@ -341,6 +362,17 @@
"support-transfer-ownership tag must be empty.");
}
mSupportsTransferOwnership = true;
+ } else if (tagName.equals("headless-system-user")) {
+ String deviceOwnerModeStringValue =
+ parser.getAttributeValue(null, "device-owner-mode");
+
+ if (deviceOwnerModeStringValue.equalsIgnoreCase("unsupported")) {
+ mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
+ } else if (deviceOwnerModeStringValue.equalsIgnoreCase("affiliated")) {
+ mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
+ } else {
+ throw new XmlPullParserException("headless-system-user mode must be valid");
+ }
}
}
} catch (NameNotFoundException e) {
@@ -355,6 +387,7 @@
mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source);
mUsesPolicies = source.readInt();
mSupportsTransferOwnership = source.readBoolean();
+ mHeadlessDeviceOwnerMode = source.readInt();
}
/**
@@ -460,6 +493,14 @@
return mSupportsTransferOwnership;
}
+ /**
+ * Returns the mode this DeviceAdmin wishes to use if provisioned as a Device Owner on a
+ * headless system user mode device.
+ */
+ public @HeadlessDeviceOwnerMode int getHeadlessDeviceOwnerMode() {
+ return mHeadlessDeviceOwnerMode;
+ }
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public ArrayList<PolicyInfo> getUsedPolicies() {
@@ -505,6 +546,7 @@
mActivityInfo.writeToParcel(dest, flags);
dest.writeInt(mUsesPolicies);
dest.writeBoolean(mSupportsTransferOwnership);
+ dest.writeInt(mHeadlessDeviceOwnerMode);
}
/**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 11584cc..7e5523a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,10 +16,10 @@
package android.app.admin;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
-import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -2812,6 +2812,17 @@
public static final int STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS = 15;
/**
+ * Result code for {@link #checkProvisioningPrecondition}.
+ *
+ * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} when provisioning a DPC which does
+ * not support headless system user mode on a headless system user mode device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED = 16;
+
+ /**
* Result codes for {@link #checkProvisioningPrecondition} indicating all the provisioning pre
* conditions.
*
@@ -2824,7 +2835,8 @@
STATUS_HAS_PAIRED, STATUS_MANAGED_USERS_NOT_SUPPORTED, STATUS_SYSTEM_USER,
STATUS_CANNOT_ADD_MANAGED_PROFILE, STATUS_DEVICE_ADMIN_NOT_SUPPORTED,
STATUS_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER,
- STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS
+ STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS,
+ STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED
})
public @interface ProvisioningPrecondition {}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index ddeb2f9..e750f49 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -407,16 +407,19 @@
}
/**
- * Enable/disable the framework backup scheduling entirely for the current user. When disabled,
+ * Enable/disable the framework backup scheduling entirely for the context user. When disabled,
* no Key/Value or Full backup jobs will be scheduled by the Android framework.
*
* <p>Note: This does not disable backups: only their scheduling is affected and backups can
* still be triggered manually.
*
- * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method. If the
+ * context user is different from the calling user, then the caller must additionally hold the
+ * android.permission.INTERACT_ACROSS_USERS_FULL permission.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(allOf = {android.Manifest.permission.BACKUP,
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
public void setFrameworkSchedulingEnabled(boolean isEnabled) {
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index e35e359..7cb6c34 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -41,7 +41,7 @@
* @hide
*/
@SystemApi
-@SystemService(Context.TIME_MANAGER)
+@SystemService(Context.TIME_MANAGER_SERVICE)
public final class TimeManager {
private static final String TAG = "time.TimeManager";
private static final boolean DEBUG = false;
diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java
index 5fd39fe..0958a806 100644
--- a/core/java/android/companion/AssociationInfo.java
+++ b/core/java/android/companion/AssociationInfo.java
@@ -56,6 +56,7 @@
private final boolean mSelfManaged;
private final boolean mNotifyOnDeviceNearby;
+ private final int mSystemDataSyncFlags;
/**
* Indicates that the association has been revoked (removed), but we keep the association
@@ -73,7 +74,6 @@
/**
* Creates a new Association.
- * Only to be used by the CompanionDeviceManagerService.
*
* @hide
*/
@@ -81,7 +81,7 @@
@Nullable MacAddress macAddress, @Nullable CharSequence displayName,
@Nullable String deviceProfile, @Nullable AssociatedDevice associatedDevice,
boolean selfManaged, boolean notifyOnDeviceNearby, boolean revoked,
- long timeApprovedMs, long lastTimeConnectedMs) {
+ long timeApprovedMs, long lastTimeConnectedMs, int systemDataSyncFlags) {
if (id <= 0) {
throw new IllegalArgumentException("Association ID should be greater than 0");
}
@@ -105,6 +105,7 @@
mRevoked = revoked;
mTimeApprovedMs = timeApprovedMs;
mLastTimeConnectedMs = lastTimeConnectedMs;
+ mSystemDataSyncFlags = systemDataSyncFlags;
}
/**
@@ -221,6 +222,16 @@
}
/**
+ * @return Enabled system data sync flags set via
+ * {@link CompanionDeviceManager#enableSystemDataSync(int, int)} and
+ * {@link CompanionDeviceManager#disableSystemDataSync(int, int)}.
+ * Or by default all flags are 1 (enabled).
+ */
+ public int getSystemDataSyncFlags() {
+ return mSystemDataSyncFlags;
+ }
+
+ /**
* Utility method for checking if the association represents a device with the given MAC
* address.
*
@@ -287,6 +298,7 @@
+ ", mLastTimeConnectedMs=" + (
mLastTimeConnectedMs == Long.MAX_VALUE
? LAST_TIME_CONNECTED_NONE : new Date(mLastTimeConnectedMs))
+ + ", mSystemDataSyncFlags=" + mSystemDataSyncFlags
+ '}';
}
@@ -306,14 +318,15 @@
&& Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress)
&& Objects.equals(mDisplayName, that.mDisplayName)
&& Objects.equals(mDeviceProfile, that.mDeviceProfile)
- && Objects.equals(mAssociatedDevice, that.mAssociatedDevice);
+ && Objects.equals(mAssociatedDevice, that.mAssociatedDevice)
+ && mSystemDataSyncFlags == that.mSystemDataSyncFlags;
}
@Override
public int hashCode() {
return Objects.hash(mId, mUserId, mPackageName, mDeviceMacAddress, mDisplayName,
mDeviceProfile, mAssociatedDevice, mSelfManaged, mNotifyOnDeviceNearby, mRevoked,
- mTimeApprovedMs, mLastTimeConnectedMs);
+ mTimeApprovedMs, mLastTimeConnectedMs, mSystemDataSyncFlags);
}
@Override
@@ -338,6 +351,7 @@
dest.writeBoolean(mRevoked);
dest.writeLong(mTimeApprovedMs);
dest.writeLong(mLastTimeConnectedMs);
+ dest.writeInt(mSystemDataSyncFlags);
}
private AssociationInfo(@NonNull Parcel in) {
@@ -356,6 +370,7 @@
mRevoked = in.readBoolean();
mTimeApprovedMs = in.readLong();
mLastTimeConnectedMs = in.readLong();
+ mSystemDataSyncFlags = in.readInt();
}
@NonNull
@@ -390,27 +405,24 @@
return new Builder(info);
}
- /**
- * @hide
- */
+ /** @hide */
public static final class Builder implements NonActionableBuilder {
@NonNull
private final AssociationInfo mOriginalInfo;
private boolean mNotifyOnDeviceNearby;
private boolean mRevoked;
private long mLastTimeConnectedMs;
+ private int mSystemDataSyncFlags;
private Builder(@NonNull AssociationInfo info) {
mOriginalInfo = info;
mNotifyOnDeviceNearby = info.mNotifyOnDeviceNearby;
mRevoked = info.mRevoked;
mLastTimeConnectedMs = info.mLastTimeConnectedMs;
+ mSystemDataSyncFlags = info.mSystemDataSyncFlags;
}
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@Override
@NonNull
public Builder setLastTimeConnected(long lastTimeConnectedMs) {
@@ -423,10 +435,7 @@
return this;
}
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@Override
@NonNull
public Builder setNotifyOnDeviceNearby(boolean notifyOnDeviceNearby) {
@@ -434,10 +443,7 @@
return this;
}
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@Override
@NonNull
public Builder setRevoked(boolean revoked) {
@@ -445,9 +451,15 @@
return this;
}
- /**
- * @hide
- */
+ /** @hide */
+ @Override
+ @NonNull
+ public Builder setSystemDataSyncFlags(int flags) {
+ mSystemDataSyncFlags = flags;
+ return this;
+ }
+
+ /** @hide */
@NonNull
public AssociationInfo build() {
return new AssociationInfo(
@@ -462,7 +474,8 @@
mNotifyOnDeviceNearby,
mRevoked,
mOriginalInfo.mTimeApprovedMs,
- mLastTimeConnectedMs
+ mLastTimeConnectedMs,
+ mSystemDataSyncFlags
);
}
}
@@ -480,25 +493,20 @@
* @hide
*/
public interface NonActionableBuilder {
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@NonNull
Builder setNotifyOnDeviceNearby(boolean notifyOnDeviceNearby);
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@NonNull
Builder setLastTimeConnected(long lastTimeConnectedMs);
- /**
- * Should only be used by the CompanionDeviceManagerService.
- * @hide
- */
+ /** @hide */
@NonNull
Builder setRevoked(boolean revoked);
+
+ /** @hide */
+ @NonNull
+ Builder setSystemDataSyncFlags(int flags);
}
}
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index d31124d..baa88e4 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -166,6 +166,19 @@
*/
public static final String REASON_CANCELED = "canceled";
+ /** @hide */
+ @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+ FLAG_CALL_METADATA,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DataSyncTypes {}
+
+ /**
+ * Used by {@link #enableSystemDataSync(int, int)}}.
+ * Sync call metadata like muting, ending and silencing a call.
+ *
+ */
+ public static final int FLAG_CALL_METADATA = 1;
/**
* A device, returned in the activity result of the {@link IntentSender} received in
@@ -468,6 +481,49 @@
}
}
+ /**
+ * <p>Enable system data sync (it only supports call metadata sync for now).
+ * By default all supported system data types are enabled.</p>
+ *
+ * <p>Calling this API requires a uses-feature
+ * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+ *
+ * @param associationId id of the device association.
+ * @param flags system data types to be enabled.
+ */
+ public void enableSystemDataSync(int associationId, @DataSyncTypes int flags) {
+ if (!checkFeaturePresent()) {
+ return;
+ }
+
+ try {
+ mService.enableSystemDataSync(associationId, flags);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * <p>Disable system data sync (it only supports call metadata sync for now).
+ * By default all supported system data types are enabled.</p>
+ *
+ * <p>Calling this API requires a uses-feature
+ * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+ *
+ * @param associationId id of the device association.
+ * @param flags system data types to be disabled.
+ */
+ public void disableSystemDataSync(int associationId, @DataSyncTypes int flags) {
+ if (!checkFeaturePresent()) {
+ return;
+ }
+
+ try {
+ mService.disableSystemDataSync(associationId, flags);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* <p>Calling this API requires a uses-feature
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 24ef52b..010aa8f 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -84,4 +84,8 @@
boolean isCompanionApplicationBound(String packageName, int userId);
PendingIntent buildAssociationCancellationIntent(in String callingPackage, int userId);
+
+ void enableSystemDataSync(int associationId, int flags);
+
+ void disableSystemDataSync(int associationId, int flags);
}
diff --git a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
index e96a2c1..4f49b8d 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceManager.aidl
@@ -18,6 +18,7 @@
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
+import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceParams;
import android.hardware.display.IVirtualDisplayCallback;
@@ -41,10 +42,12 @@
* @param params The parameters for creating this virtual device. See {@link
* VirtualDeviceManager.VirtualDeviceParams}.
* @param activityListener The listener to listen for activity changes in a virtual device.
+ * @param soundEffectListener The listener to listen for sound effect playback requests.
*/
IVirtualDevice createVirtualDevice(
in IBinder token, String packageName, int associationId,
- in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener);
+ in VirtualDeviceParams params, in IVirtualDeviceActivityListener activityListener,
+ in IVirtualDeviceSoundEffectListener soundEffectListener);
/**
* Returns the details of all available virtual devices.
@@ -92,4 +95,13 @@
* if there's none.
*/
int getAudioRecordingSessionId(int deviceId);
+
+ /**
+ * Triggers sound effect playback on virtual device.
+ *
+ * @param deviceId id of the virtual device.
+ * @param sound effect type corresponding to
+ * {@code android.media.AudioManager.SystemSoundEffect}
+ */
+ void playSoundEffect(int deviceId, int effectType);
}
diff --git a/core/java/android/companion/virtual/IVirtualDeviceSoundEffectListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceSoundEffectListener.aidl
new file mode 100644
index 0000000..91c209f
--- /dev/null
+++ b/core/java/android/companion/virtual/IVirtualDeviceSoundEffectListener.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.companion.virtual;
+
+/**
+ * Interface to listen for sound effect playback on Virtual Device.
+ *
+ * @hide
+ */
+oneway interface IVirtualDeviceSoundEffectListener {
+
+
+ /**
+ * Called when there's sound effect to be played on Virtual Device.
+ *
+ * @param sound effect type corresponding to
+ * {@code android.media.AudioManager.SystemSoundEffect}
+ */
+ void onPlaySoundEffect(int effectType);
+}
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 3bc1628..1bc3091 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -69,6 +69,8 @@
import android.util.Log;
import android.view.Surface;
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -333,10 +335,15 @@
* @hide
*/
public void playSoundEffect(int deviceId, @AudioManager.SystemSoundEffect int effectType) {
- //TODO - handle requests to play sound effects by custom callbacks or SoundPool asociated
- // with device session id.
- // For now, this is intentionally left empty and effectively disables sound effects for
- // virtual devices with custom device audio policy.
+ if (mService == null) {
+ Log.w(TAG, "Failed to dispatch sound effect; no virtual device manager service.");
+ return;
+ }
+ try {
+ mService.playSoundEffect(deviceId, effectType);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -359,6 +366,10 @@
private final ArrayMap<IntentInterceptorCallback,
VirtualIntentInterceptorDelegate> mIntentInterceptorListeners =
new ArrayMap<>();
+ private final Object mSoundEffectListenersLock = new Object();
+ @GuardedBy("mSoundEffectListenersLock")
+ private final ArrayMap<SoundEffectListener, SoundEffectListenerDelegate>
+ mSoundEffectListeners = new ArrayMap<>();
private final IVirtualDeviceActivityListener mActivityListenerBinder =
new IVirtualDeviceActivityListener.Stub() {
@@ -387,6 +398,22 @@
}
}
};
+ private final IVirtualDeviceSoundEffectListener mSoundEffectListener =
+ new IVirtualDeviceSoundEffectListener.Stub() {
+ @Override
+ public void onPlaySoundEffect(int soundEffect) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mSoundEffectListenersLock) {
+ for (int i = 0; i < mSoundEffectListeners.size(); i++) {
+ mSoundEffectListeners.valueAt(i).onPlaySoundEffect(soundEffect);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
@Nullable
private VirtualCameraDevice mVirtualCameraDevice;
@NonNull
@@ -407,7 +434,8 @@
mContext.getPackageName(),
associationId,
params,
- mActivityListenerBinder);
+ mActivityListenerBinder,
+ mSoundEffectListener);
final List<VirtualSensorConfig> virtualSensorConfigs = params.getVirtualSensorConfigs();
for (int i = 0; i < virtualSensorConfigs.size(); ++i) {
mVirtualSensors.add(createVirtualSensor(virtualSensorConfigs.get(i)));
@@ -947,6 +975,35 @@
}
/**
+ * Adds a sound effect listener.
+ *
+ * @param executor The executor where the listener is executed on.
+ * @param soundEffectListener The listener to add.
+ * @see #removeActivityListener(ActivityListener)
+ */
+ public void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor,
+ @NonNull SoundEffectListener soundEffectListener) {
+ final SoundEffectListenerDelegate delegate =
+ new SoundEffectListenerDelegate(Objects.requireNonNull(executor),
+ Objects.requireNonNull(soundEffectListener));
+ synchronized (mSoundEffectListenersLock) {
+ mSoundEffectListeners.put(soundEffectListener, delegate);
+ }
+ }
+
+ /**
+ * Removes a sound effect listener previously added with {@link #addActivityListener}.
+ *
+ * @param soundEffectListener The listener to remove.
+ * @see #addActivityListener(Executor, ActivityListener)
+ */
+ public void removeSoundEffectListener(@NonNull SoundEffectListener soundEffectListener) {
+ synchronized (mSoundEffectListenersLock) {
+ mSoundEffectListeners.remove(soundEffectListener);
+ }
+ }
+
+ /**
* Registers an intent interceptor that will intercept an intent attempting to launch
* when matching the provided IntentFilter and calls the callback with the intercepted
* intent.
@@ -1090,4 +1147,38 @@
}
}
}
+
+ /**
+ * Listener for system sound effect playback on virtual device.
+ * @hide
+ */
+ @SystemApi
+ public interface SoundEffectListener {
+
+ /**
+ * Called when there's a system sound effect to be played on virtual device.
+ *
+ * @param effectType - system sound effect type, see
+ * {@code android.media.AudioManager.SystemSoundEffect}
+ */
+ void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType);
+ }
+
+ /**
+ * A wrapper for {@link SoundEffectListener} that executes callbacks on the given executor.
+ */
+ private static class SoundEffectListenerDelegate {
+ @NonNull private final SoundEffectListener mSoundEffectListener;
+ @NonNull private final Executor mExecutor;
+
+ private SoundEffectListenerDelegate(Executor executor,
+ SoundEffectListener soundEffectCallback) {
+ mSoundEffectListener = soundEffectCallback;
+ mExecutor = executor;
+ }
+
+ public void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType) {
+ mExecutor.execute(() -> mSoundEffectListener.onPlaySoundEffect(effectType));
+ }
+ }
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a58cac3..7310138 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5854,7 +5854,7 @@
public static final String SECURE_ELEMENT_SERVICE = "secure_element";
/**
- * Use with {@link #getSystemService(String)} to retrieve an
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.timedetector.TimeDetector}.
* @hide
*
@@ -5863,7 +5863,7 @@
public static final String TIME_DETECTOR_SERVICE = "time_detector";
/**
- * Use with {@link #getSystemService(String)} to retrieve an
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.app.timezonedetector.TimeZoneDetector}.
* @hide
*
@@ -5872,12 +5872,14 @@
public static final String TIME_ZONE_DETECTOR_SERVICE = "time_zone_detector";
/**
- * Use with {@link #getSystemService(String)} to retrieve an {@link TimeManager}.
+ * Use with {@link #getSystemService(String)} to retrieve a {@link TimeManager}.
* @hide
*
* @see #getSystemService(String)
*/
- public static final String TIME_MANAGER = "time_manager";
+ @SystemApi
+ @SuppressLint("ServiceName")
+ public static final String TIME_MANAGER_SERVICE = "time_manager";
/**
* Binder service name for {@link AppBindingService}.
@@ -7527,14 +7529,12 @@
}
/**
- * Get the binder object associated with the IApplicationThread of this Context.
- *
- * This can be used by a mainline module to uniquely identify a specific app process.
+ * Used by a mainline module to uniquely identify a specific app process.
* @hide
*/
@NonNull
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public IBinder getIApplicationThreadBinder() {
+ public IBinder getProcessToken() {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index e65e91c..9027e2e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1286,8 +1286,8 @@
* @hide
*/
@Override
- public IBinder getIApplicationThreadBinder() {
- return mBase.getIApplicationThreadBinder();
+ public IBinder getProcessToken() {
+ return mBase.getProcessToken();
}
/**
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 8fd905e..e803084 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -998,6 +998,7 @@
Configuration.NATIVE_CONFIG_DENSITY, // DENSITY
Configuration.NATIVE_CONFIG_LAYOUTDIR, // LAYOUT DIRECTION
Configuration.NATIVE_CONFIG_COLOR_MODE, // COLOR_MODE
+ Configuration.NATIVE_CONFIG_GRAMMATICAL_GENDER,
};
/**
@@ -1302,8 +1303,8 @@
* {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
* {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
* {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT},
- * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION} and
- * {@link #CONFIG_COLOR_MODE}.
+ * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION},
+ * {@link #CONFIG_COLOR_MODE}, and {link #CONFIG_GRAMMATICAL_GENDER}.
* Set from the {@link android.R.attr#configChanges} attribute.
*/
public int configChanges;
diff --git a/core/java/android/content/pm/ApkChecksum.java b/core/java/android/content/pm/ApkChecksum.java
index d550f41..88a1960 100644
--- a/core/java/android/content/pm/ApkChecksum.java
+++ b/core/java/android/content/pm/ApkChecksum.java
@@ -36,7 +36,7 @@
*
* @see PackageManager#requestChecksums
*/
-@DataClass(genHiddenConstructor = true)
+@DataClass(genHiddenConstructor = true, genToString = true)
@DataClass.Suppress({"getChecksum"})
public final class ApkChecksum implements Parcelable {
/**
@@ -178,6 +178,20 @@
@Override
@DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "ApkChecksum { " +
+ "splitName = " + mSplitName + ", " +
+ "checksum = " + mChecksum + ", " +
+ "installerPackageName = " + mInstallerPackageName + ", " +
+ "installerCertificate = " + java.util.Arrays.toString(mInstallerCertificate) +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
@@ -235,10 +249,10 @@
};
@DataClass.Generated(
- time = 1619810171079L,
+ time = 1674080488372L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/ApkChecksum.java",
- inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mInstallerPackageName\nprivate final @android.annotation.Nullable byte[] mInstallerCertificate\npublic @android.content.pm.Checksum.Type int getType()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getInstallerCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getInstallerCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mInstallerPackageName\nprivate final @android.annotation.Nullable byte[] mInstallerCertificate\npublic @android.content.pm.Checksum.Type int getType()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getInstallerCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getInstallerCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 047f8c1..3430a61 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -572,26 +572,8 @@
boolean performDexOptSecondary(String packageName,
String targetCompilerFilter, boolean force);
- /**
- * Ask the package manager to dump profiles associated with a package.
- *
- * @param packageName The name of the package to dump.
- * @param dumpClassesAndMethods If false, pass {@code --dump-only} to profman to dump the
- * profile in a human readable form intended for debugging. If true, pass
- * {@code --dump-classes-and-methods} to profman to dump a sorted list of classes and methods
- * in a human readable form that is valid input for {@code profman --create-profile-from}.
- */
- void dumpProfiles(String packageName, boolean dumpClassesAndMethods);
-
void forceDexOpt(String packageName);
- /**
- * Reconcile the information we have about the secondary dex files belonging to
- * {@code packagName} and the actual dex files. For all dex files that were
- * deleted, update the internal records and delete the generated oat files.
- */
- void reconcileSecondaryDexFiles(String packageName);
-
int getMoveStatus(int moveId);
void registerMoveCallback(in IPackageMoveObserver callback);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index da36da5..1a6f6b8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -783,6 +783,7 @@
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ MATCH_CLONE_PROFILE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResolveInfoFlagsBits {}
@@ -1113,6 +1114,19 @@
public static final int MATCH_DIRECT_BOOT_AUTO = 0x10000000;
/**
+ * {@link ResolveInfo} flag: allow matching components across clone profile
+ * <p>
+ * This flag is used only for query and not resolution, the default behaviour would be to
+ * restrict querying across clone profile. This flag would be honored only if caller have
+ * permission {@link Manifest.permission.QUERY_CLONED_APPS}.
+ *
+ * @hide
+ * <p>
+ */
+ @SystemApi
+ public static final int MATCH_CLONE_PROFILE = 0x20000000;
+
+ /**
* {@link PackageInfo} flag: return all attributions declared in the package manifest
*/
public static final int GET_ATTRIBUTIONS = 0x80000000;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c15b3e0..048289f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1456,7 +1456,7 @@
private static AssetManager newConfiguredAssetManager() {
AssetManager assetManager = new AssetManager();
- assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
return assetManager;
}
@@ -9011,7 +9011,7 @@
}
AssetManager assets = new AssetManager();
- assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
@@ -9086,7 +9086,7 @@
private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
final AssetManager assets = new AssetManager();
- assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
return assets;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 0b503eb..6ca708a 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -426,6 +426,8 @@
* the {@link android.R.attr#foregroundServiceType} attribute.
* The file management use case which manages files/directories, often involving file I/O
* across the file system.
+ *
+ * @hide
*/
@RequiresPermission(
value = Manifest.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 44747fa..e38cb65 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -406,24 +406,6 @@
}
/**
- * Returns true if the user is a split system user.
- * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
- * the method always returns false.
- */
- public boolean isSystemOnly() {
- return isSystemOnly(id);
- }
-
- /**
- * Returns true if the given user is a split system user.
- * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
- * the method always returns false.
- */
- public static boolean isSystemOnly(int userId) {
- return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
- }
-
- /**
* @return true if this user can be switched to.
**/
public boolean supportsSwitchTo() {
@@ -454,7 +436,7 @@
if (isProfile() || isGuest() || isRestricted()) {
return false;
}
- if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
+ if (UserManager.isHeadlessSystemUserMode()) {
return id != UserHandle.USER_SYSTEM;
} else {
return id == UserHandle.USER_SYSTEM;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index c8bbb0c1..dfc7b464 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1461,13 +1461,14 @@
public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation,
int touchscreen, int density, int keyboard, int keyboardHidden, int navigation,
int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp,
- int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) {
+ int screenHeightDp, int screenLayout, int uiMode, int colorMode, int grammaticalGender,
+ int majorVersion) {
synchronized (this) {
ensureValidLocked();
nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density,
keyboard, keyboardHidden, navigation, screenWidth, screenHeight,
smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode,
- colorMode, majorVersion);
+ colorMode, grammaticalGender, majorVersion);
}
}
@@ -1557,7 +1558,7 @@
@Nullable String locale, int orientation, int touchscreen, int density, int keyboard,
int keyboardHidden, int navigation, int screenWidth, int screenHeight,
int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
- int uiMode, int colorMode, int majorVersion);
+ int uiMode, int colorMode, int grammaticalGender, int majorVersion);
private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
long ptr, boolean includeOverlays, boolean includeLoaders);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 96aa624..0def59f 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -20,6 +20,7 @@
import static android.content.ConfigurationProto.DENSITY_DPI;
import static android.content.ConfigurationProto.FONT_SCALE;
import static android.content.ConfigurationProto.FONT_WEIGHT_ADJUSTMENT;
+import static android.content.ConfigurationProto.GRAMMATICAL_GENDER;
import static android.content.ConfigurationProto.HARD_KEYBOARD_HIDDEN;
import static android.content.ConfigurationProto.KEYBOARD;
import static android.content.ConfigurationProto.KEYBOARD_HIDDEN;
@@ -167,19 +168,19 @@
* Constant for grammatical gender: to indicate the terms of address the user
* preferred in an application is neuter.
*/
- public static final int GRAMMATICAL_GENDER_NEUTRAL = 2;
+ public static final int GRAMMATICAL_GENDER_NEUTRAL = 1;
/**
* Constant for grammatical gender: to indicate the terms of address the user
* preferred in an application is feminine.
*/
- public static final int GRAMMATICAL_GENDER_FEMININE = 3;
+ public static final int GRAMMATICAL_GENDER_FEMININE = 2;
/**
* Constant for grammatical gender: to indicate the terms of address the user
* preferred in an application is masculine.
*/
- public static final int GRAMMATICAL_GENDER_MASCULINE = 4;
+ public static final int GRAMMATICAL_GENDER_MASCULINE = 3;
/** Constant for {@link #colorMode}: bits that encode whether the screen is wide gamut. */
public static final int COLOR_MODE_WIDE_COLOR_GAMUT_MASK = 0x3;
@@ -529,15 +530,10 @@
if ((diff & ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT) != 0) {
list.add("CONFIG_AUTO_BOLD_TEXT");
}
- StringBuilder builder = new StringBuilder("{");
- for (int i = 0, n = list.size(); i < n; i++) {
- builder.append(list.get(i));
- if (i != n - 1) {
- builder.append(", ");
- }
+ if ((diff & ActivityInfo.CONFIG_GRAMMATICAL_GENDER) != 0) {
+ list.add("CONFIG_GRAMMATICAL_GENDER");
}
- builder.append("}");
- return builder.toString();
+ return "{" + TextUtils.join(", ", list) + "}";
}
/**
@@ -970,6 +966,7 @@
NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
NATIVE_CONFIG_LAYOUTDIR,
NATIVE_CONFIG_COLOR_MODE,
+ NATIVE_CONFIG_GRAMMATICAL_GENDER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface NativeConfig {}
@@ -1008,6 +1005,9 @@
public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
/** @hide Native-specific bit mask for COLOR_MODE config ; DO NOT USE UNLESS YOU ARE SURE.*/
public static final int NATIVE_CONFIG_COLOR_MODE = 0x10000;
+ /** @hide Native-specific bit mask for GRAMMATICAL_GENDER config; DO NOT USE UNLESS YOU
+ * ARE SURE.*/
+ public static final int NATIVE_CONFIG_GRAMMATICAL_GENDER = 0x20000;
/**
* <p>Construct an invalid Configuration. This state is only suitable for constructing a
@@ -1112,6 +1112,14 @@
} else {
sb.append(" ?localeList");
}
+ if (mGrammaticalGender != 0) {
+ switch (mGrammaticalGender) {
+ case GRAMMATICAL_GENDER_NEUTRAL: sb.append(" neuter"); break;
+ case GRAMMATICAL_GENDER_FEMININE: sb.append(" feminine"); break;
+ case GRAMMATICAL_GENDER_MASCULINE: sb.append(" masculine"); break;
+ case GRAMMATICAL_GENDER_NOT_SPECIFIED: sb.append(" ?grgend"); break;
+ }
+ }
int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK);
switch (layoutDir) {
case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break;
@@ -1292,6 +1300,7 @@
protoOutputStream.write(ORIENTATION, orientation);
protoOutputStream.write(SCREEN_WIDTH_DP, screenWidthDp);
protoOutputStream.write(SCREEN_HEIGHT_DP, screenHeightDp);
+ protoOutputStream.write(GRAMMATICAL_GENDER, mGrammaticalGender);
protoOutputStream.end(token);
}
@@ -1454,6 +1463,9 @@
case (int) FONT_WEIGHT_ADJUSTMENT:
fontWeightAdjustment = protoInputStream.readInt(FONT_WEIGHT_ADJUSTMENT);
break;
+ case (int) GRAMMATICAL_GENDER:
+ mGrammaticalGender = protoInputStream.readInt(GRAMMATICAL_GENDER);
+ break;
}
}
} finally {
@@ -1839,6 +1851,9 @@
if ((mask & ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT) != 0) {
fontWeightAdjustment = delta.fontWeightAdjustment;
}
+ if ((mask & ActivityInfo.CONFIG_GRAMMATICAL_GENDER) != 0) {
+ mGrammaticalGender = delta.mGrammaticalGender;
+ }
}
/**
@@ -1975,7 +1990,7 @@
changed |= ActivityInfo.CONFIG_FONT_WEIGHT_ADJUSTMENT;
}
- if (!publicOnly&& mGrammaticalGender != delta.mGrammaticalGender) {
+ if (!publicOnly && mGrammaticalGender != delta.mGrammaticalGender) {
changed |= ActivityInfo.CONFIG_GRAMMATICAL_GENDER;
}
return changed;
@@ -2172,6 +2187,8 @@
if (n != 0) return n;
}
+ n = this.mGrammaticalGender - that.mGrammaticalGender;
+ if (n != 0) return n;
n = this.touchscreen - that.touchscreen;
if (n != 0) return n;
n = this.keyboard - that.keyboard;
@@ -2205,11 +2222,6 @@
n = windowConfiguration.compareTo(that.windowConfiguration);
if (n != 0) return n;
n = this.fontWeightAdjustment - that.fontWeightAdjustment;
- if (n != 0) return n;
- n = this.mGrammaticalGender - that.mGrammaticalGender;
- if (n != 0) return n;
-
- // if (n != 0) return n;
return n;
}
@@ -2482,6 +2494,20 @@
}
}
+ switch (config.mGrammaticalGender) {
+ case Configuration.GRAMMATICAL_GENDER_NEUTRAL:
+ parts.add("neuter");
+ break;
+ case Configuration.GRAMMATICAL_GENDER_FEMININE:
+ parts.add("feminine");
+ break;
+ case Configuration.GRAMMATICAL_GENDER_MASCULINE:
+ parts.add("masculine");
+ break;
+ default:
+ break;
+ }
+
switch (config.screenLayout & Configuration.SCREENLAYOUT_LAYOUTDIR_MASK) {
case Configuration.SCREENLAYOUT_LAYOUTDIR_LTR:
parts.add("ldltr");
@@ -2768,6 +2794,10 @@
delta.locale = change.locale;
}
+ if (base.mGrammaticalGender != change.mGrammaticalGender) {
+ delta.mGrammaticalGender = change.mGrammaticalGender;
+ }
+
if (base.touchscreen != change.touchscreen) {
delta.touchscreen = change.touchscreen;
}
@@ -2881,6 +2911,7 @@
private static final String XML_ATTR_DENSITY = "density";
private static final String XML_ATTR_APP_BOUNDS = "app_bounds";
private static final String XML_ATTR_FONT_WEIGHT_ADJUSTMENT = "fontWeightAdjustment";
+ private static final String XML_ATTR_GRAMMATICAL_GENDER = "grammaticalGender";
/**
* Reads the attributes corresponding to Configuration member fields from the Xml parser.
@@ -2932,6 +2963,8 @@
DENSITY_DPI_UNDEFINED);
configOut.fontWeightAdjustment = XmlUtils.readIntAttribute(parser,
XML_ATTR_FONT_WEIGHT_ADJUSTMENT, FONT_WEIGHT_ADJUSTMENT_UNDEFINED);
+ configOut.mGrammaticalGender = XmlUtils.readIntAttribute(parser,
+ XML_ATTR_GRAMMATICAL_GENDER, GRAMMATICAL_GENDER_NOT_SPECIFIED);
// For persistence, we don't care about assetsSeq and WindowConfiguration, so do not read it
// out.
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index c77a372..ffdc7b38 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -42,7 +42,7 @@
/* fromSp= */
new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100},
/* toDp= */
- new float[] { 9.2f, 11.5f, 13.8f, 16.1f, 20.7f, 23f, 27.6f, 34.5f, 115})
+ new float[] { 9.2f, 11.5f, 13.8f, 16.4f, 19.8f, 21.8f, 25.2f, 30f, 100})
);
put(
@@ -51,7 +51,7 @@
/* fromSp= */
new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100},
/* toDp= */
- new float[] {10.4f, 13f, 15.6f, 18.2f, 23.4f, 26f, 31.2f, 39f, 130})
+ new float[] {10.4f, 13f, 15.6f, 18.8f, 21.6f, 23.6f, 26.4f, 30f, 100})
);
put(
@@ -60,7 +60,7 @@
/* fromSp= */
new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100},
/* toDp= */
- new float[] { 12f, 15f, 18f, 21f, 27f, 30f, 36f, 45f, 150})
+ new float[] { 12f, 15f, 18f, 22f, 24f, 26f, 28f, 30f, 100})
);
put(
@@ -69,7 +69,7 @@
/* fromSp= */
new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100},
/* toDp= */
- new float[] {14.4f, 18f, 21.6f, 25.2f, 32.4f, 36f, 43.2f, 54f, 180})
+ new float[] {14.4f, 18f, 21.6f, 24.4f, 27.6f, 30.8f, 32.8f, 34.8f, 100})
);
put(
@@ -78,7 +78,7 @@
/* fromSp= */
new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100},
/* toDp= */
- new float[] { 16f, 20f, 24f, 28f, 36f, 40f, 48f, 60f, 200})
+ new float[] { 16f, 20f, 24f, 26f, 30f, 34f, 36f, 38f, 100})
);
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index c2b3769..2170886 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -466,7 +466,8 @@
mConfiguration.smallestScreenWidthDp,
mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
mConfiguration.screenLayout, mConfiguration.uiMode,
- mConfiguration.colorMode, Build.VERSION.RESOURCES_SDK_INT);
+ mConfiguration.colorMode, mConfiguration.getGrammaticalGender(),
+ Build.VERSION.RESOURCES_SDK_INT);
if (DEBUG_CONFIG) {
Slog.i(TAG, "**** Updating config of " + this + ": final config is "
diff --git a/core/java/android/credentials/CreateCredentialException.java b/core/java/android/credentials/CreateCredentialException.java
index fefa60a..84cc9a8 100644
--- a/core/java/android/credentials/CreateCredentialException.java
+++ b/core/java/android/credentials/CreateCredentialException.java
@@ -28,7 +28,7 @@
/**
* Represents an error encountered during the
- * {@link CredentialManager#executeCreateCredential(CreateCredentialRequest,
+ * {@link CredentialManager#createCredential(CreateCredentialRequest,
* Activity, CancellationSignal, Executor, OutcomeReceiver)} operation.
*/
public class CreateCredentialException extends Exception {
@@ -41,7 +41,7 @@
/**
* The error type value for when no credential is available for the given {@link
- * CredentialManager#executeCreateCredential(CreateCredentialRequest, Activity,
+ * CredentialManager#createCredential(CreateCredentialRequest, Activity,
* CancellationSignal, Executor, OutcomeReceiver)} request.
*/
@NonNull
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index be887a5..26f8831 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -54,7 +54,7 @@
/**
* Determines whether the request must only be fulfilled by a system provider.
*/
- private final boolean mRequireSystemProvider;
+ private final boolean mIsSystemProviderRequired;
/**
* Returns the requested credential type.
@@ -99,8 +99,8 @@
* Returns true if the request must only be fulfilled by a system provider, and false
* otherwise.
*/
- public boolean requireSystemProvider() {
- return mRequireSystemProvider;
+ public boolean isSystemProviderRequired() {
+ return mIsSystemProviderRequired;
}
@Override
@@ -108,7 +108,7 @@
dest.writeString8(mType);
dest.writeBundle(mCredentialData);
dest.writeBundle(mCandidateQueryData);
- dest.writeBoolean(mRequireSystemProvider);
+ dest.writeBoolean(mIsSystemProviderRequired);
}
@Override
@@ -122,7 +122,7 @@
+ "type=" + mType
+ ", credentialData=" + mCredentialData
+ ", candidateQueryData=" + mCandidateQueryData
- + ", requireSystemProvider=" + mRequireSystemProvider
+ + ", isSystemProviderRequired=" + mIsSystemProviderRequired
+ "}";
}
@@ -133,7 +133,8 @@
* @param credentialData the full credential creation request data
* @param candidateQueryData the partial request data that will be sent to the provider
* during the initial creation candidate query stage
- * @param requireSystemProvider whether the request must only be fulfilled by a system provider
+ * @param isSystemProviderRequired whether the request must only be fulfilled by a system
+ * provider
*
* @throws IllegalArgumentException If type is empty.
*/
@@ -141,19 +142,19 @@
@NonNull String type,
@NonNull Bundle credentialData,
@NonNull Bundle candidateQueryData,
- boolean requireSystemProvider) {
+ boolean isSystemProviderRequired) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
"candidateQueryData must not be null");
- mRequireSystemProvider = requireSystemProvider;
+ mIsSystemProviderRequired = isSystemProviderRequired;
}
private CreateCredentialRequest(@NonNull Parcel in) {
String type = in.readString8();
Bundle credentialData = in.readBundle();
Bundle candidateQueryData = in.readBundle();
- boolean requireSystemProvider = in.readBoolean();
+ boolean isSystemProviderRequired = in.readBoolean();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
@@ -161,7 +162,7 @@
AnnotationValidations.validate(NonNull.class, null, mCredentialData);
mCandidateQueryData = candidateQueryData;
AnnotationValidations.validate(NonNull.class, null, mCandidateQueryData);
- mRequireSystemProvider = requireSystemProvider;
+ mIsSystemProviderRequired = isSystemProviderRequired;
}
public static final @NonNull Parcelable.Creator<CreateCredentialRequest> CREATOR =
diff --git a/core/java/android/credentials/CredentialDescription.aidl b/core/java/android/credentials/CredentialDescription.aidl
new file mode 100644
index 0000000..1b5739e
--- /dev/null
+++ b/core/java/android/credentials/CredentialDescription.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright 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 android.credentials;
+
+/**
+ * @hide
+ */
+parcelable CredentialDescription;
\ No newline at end of file
diff --git a/core/java/android/credentials/CredentialDescription.java b/core/java/android/credentials/CredentialDescription.java
new file mode 100644
index 0000000..b4310f2
--- /dev/null
+++ b/core/java/android/credentials/CredentialDescription.java
@@ -0,0 +1,139 @@
+/*
+ * 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 android.credentials;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.credentials.CredentialEntry;
+
+import com.android.internal.util.AnnotationValidations;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents the type and contained data fields of a {@link Credential}.
+ * @hide
+ */
+public final class CredentialDescription implements Parcelable {
+
+ /**
+ * The credential type.
+ */
+ @NonNull
+ private final String mType;
+
+ /**
+ * The flattened JSON string that will be matched with requests.
+ */
+ @NonNull
+ private final String mFlattenedRequestString;
+
+ /**
+ * The entry to be used in the UI.
+ */
+ @NonNull
+ private final List<CredentialEntry> mCredentialEntries;
+
+ /**
+ * Constructs a {@link CredentialDescription}.
+ *
+ * @param type the type of the credential returned.
+ * @param flattenedRequestString flattened JSON string that will be matched with requests.
+ * @param credentialEntries a list of {@link CredentialEntry}s that have been returned
+ * to the developer upon credential creation.
+ *
+ * @throws IllegalArgumentException If type is empty.
+ */
+ public CredentialDescription(@NonNull String type,
+ @NonNull String flattenedRequestString,
+ @NonNull List<CredentialEntry> credentialEntries) {
+ mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
+ mFlattenedRequestString = Preconditions.checkStringNotEmpty(flattenedRequestString);
+ mCredentialEntries = Objects.requireNonNull(credentialEntries);
+ }
+
+ private CredentialDescription(@NonNull Parcel in) {
+ String type = in.readString8();
+ String flattenedRequestString = in.readString();
+ List<CredentialEntry> entries = new ArrayList<>();
+ in.readTypedList(entries, CredentialEntry.CREATOR);
+
+ mType = type;
+ AnnotationValidations.validate(android.annotation.NonNull.class, null, mType);
+ mFlattenedRequestString = flattenedRequestString;
+ AnnotationValidations.validate(android.annotation.NonNull.class, null,
+ mFlattenedRequestString);
+ mCredentialEntries = entries;
+ AnnotationValidations.validate(android.annotation.NonNull.class, null,
+ mCredentialEntries);
+ }
+
+ public static final @NonNull Parcelable.Creator<CredentialDescription> CREATOR =
+ new Parcelable.Creator<CredentialDescription>() {
+ @Override
+ public CredentialDescription createFromParcel(Parcel in) {
+ return new CredentialDescription(in);
+ }
+
+ @Override
+ public CredentialDescription[] newArray(int size) {
+ return new CredentialDescription[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mType);
+ dest.writeString(mFlattenedRequestString);
+ dest.writeTypedList(mCredentialEntries, flags);
+ }
+
+ @NonNull
+ public String getType() {
+ return mType;
+ }
+
+ @NonNull
+ public String getFlattenedRequestString() {
+ return mFlattenedRequestString;
+ }
+
+ @NonNull
+ public List<CredentialEntry> getCredentialEntries() {
+ return mCredentialEntries;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mFlattenedRequestString);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return Objects.equals(mType, ((CredentialDescription) obj).getType())
+ && Objects.equals(mFlattenedRequestString, ((CredentialDescription) obj).getType());
+ }
+}
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index d4daf364..e15cec8 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -63,6 +63,14 @@
"enable_credential_manager";
/**
+ * Flag to enable and disable Credential Description api.
+ *
+ * @hide
+ */
+ private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
+ "enable_credential_description_api";
+
+ /**
* @hide instantiated by ContextImpl.
*/
public CredentialManager(Context context, ICredentialManager service) {
@@ -82,7 +90,7 @@
* @param executor the callback will take place on this {@link Executor}
* @param callback the callback invoked when the request succeeds or fails
*/
- public void executeGetCredential(
+ public void getCredential(
@NonNull GetCredentialRequest request,
@NonNull Activity activity,
@Nullable CancellationSignal cancellationSignal,
@@ -94,7 +102,7 @@
requireNonNull(callback, "callback must not be null");
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "executeGetCredential already canceled");
+ Log.w(TAG, "getCredential already canceled");
return;
}
@@ -126,7 +134,7 @@
* @param executor the callback will take place on this {@link Executor}
* @param callback the callback invoked when the request succeeds or fails
*/
- public void executeCreateCredential(
+ public void createCredential(
@NonNull CreateCredentialRequest request,
@NonNull Activity activity,
@Nullable CancellationSignal cancellationSignal,
@@ -139,7 +147,7 @@
requireNonNull(callback, "callback must not be null");
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "executeCreateCredential already canceled");
+ Log.w(TAG, "createCredential already canceled");
return;
}
@@ -185,7 +193,7 @@
requireNonNull(callback, "callback must not be null");
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "executeCreateCredential already canceled");
+ Log.w(TAG, "clearCredentialState already canceled");
return;
}
@@ -294,6 +302,112 @@
true);
}
+ /**
+ * Returns whether the credential description api is enabled.
+ *
+ * @hide
+ */
+ public static boolean isCredentialDescriptionApiEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+ }
+
+ /**
+ * Registers a {@link CredentialDescription} for an actively provisioned {@link Credential}
+ * a CredentialProvider has. This registry will then be used by
+ * {@link #executeGetCredential(GetCredentialRequest, Activity,
+ * CancellationSignal, Executor, OutcomeReceiver)} to determine where to
+ * fetch the requested {@link Credential} from.
+ *
+ *
+ * @param request the request data
+ * @param cancellationSignal an optional signal that allows for cancelling this call
+ * @param executor the callback will take place on this {@link Executor}
+ * @param callback the callback invoked when the request succeeds or fails
+ *
+ * @throws {@link UnsupportedOperationException} if the feature has not been enabled.
+ *
+ * @hide
+ */
+ public void registerCredentialDescription(
+ @NonNull RegisterCredentialDescriptionRequest request,
+ @Nullable CancellationSignal cancellationSignal,
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull OutcomeReceiver<Void, RegisterCredentialDescriptionException> callback) {
+
+ if (!isCredentialDescriptionApiEnabled()) {
+ throw new UnsupportedOperationException("This API is not currently supported.");
+ }
+
+ requireNonNull(executor, "executor must not be null");
+ requireNonNull(callback, "callback must not be null");
+
+ if (cancellationSignal != null && cancellationSignal.isCanceled()) {
+ Log.w(TAG, "executeCreateCredential already canceled");
+ return;
+ }
+
+ ICancellationSignal cancelRemote = null;
+ try {
+ cancelRemote = mService.registerCredentialDescription(request,
+ new RegisterCredentialDescriptionTransport(executor, callback),
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
+ if (cancellationSignal != null && cancelRemote != null) {
+ cancellationSignal.setRemote(cancelRemote);
+ }
+ }
+
+
+ /**
+ * Unregisters a {@link CredentialDescription} for an actively provisioned {@link Credential}
+ * that has been registered previously.
+ *
+ *
+ * @param request the request data
+ * @param cancellationSignal an optional signal that allows for cancelling this call
+ * @param executor the callback will take place on this {@link Executor}
+ * @param callback the callback invoked when the request succeeds or fails
+ *
+ * @throws {@link UnsupportedOperationException} if the feature has not been enabled.
+ *
+ * @hide
+ */
+ public void unRegisterCredentialDescription(
+ @NonNull UnregisterCredentialDescriptionRequest request,
+ @Nullable CancellationSignal cancellationSignal,
+ @CallbackExecutor @NonNull Executor executor,
+ @NonNull OutcomeReceiver<Void, UnregisterCredentialDescriptionException> callback) {
+
+ if (!isCredentialDescriptionApiEnabled()) {
+ throw new UnsupportedOperationException("This API is not currently supported.");
+ }
+
+ requireNonNull(executor, "executor must not be null");
+ requireNonNull(callback, "callback must not be null");
+
+ if (cancellationSignal != null && cancellationSignal.isCanceled()) {
+ Log.w(TAG, "executeCreateCredential already canceled");
+ return;
+ }
+
+ ICancellationSignal cancelRemote = null;
+ try {
+ cancelRemote = mService.unRegisterCredentialDescription(request,
+ new UnregisterCredentialDescriptionTransport(executor, callback),
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
+ if (cancellationSignal != null && cancelRemote != null) {
+ cancellationSignal.setRemote(cancelRemote);
+ }
+ }
+
private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
// TODO: listen for cancellation to release callback.
@@ -455,4 +569,54 @@
() -> mCallback.onError(new SetEnabledProvidersException(errorType, message)));
}
}
+
+ private static class RegisterCredentialDescriptionTransport
+ extends IRegisterCredentialDescriptionCallback.Stub {
+
+ private final Executor mExecutor;
+ private final OutcomeReceiver<Void, RegisterCredentialDescriptionException> mCallback;
+
+ private RegisterCredentialDescriptionTransport(Executor executor,
+ OutcomeReceiver<Void, RegisterCredentialDescriptionException> callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onResponse() {
+ mCallback.onResult(null);
+ }
+
+ @Override
+ public void onError(String errorCode, String message) {
+ mExecutor.execute(
+ () -> mCallback.onError(new RegisterCredentialDescriptionException(errorCode,
+ message)));
+ }
+ }
+
+ private static class UnregisterCredentialDescriptionTransport
+ extends IUnregisterCredentialDescriptionCallback.Stub {
+
+ private final Executor mExecutor;
+ private final OutcomeReceiver<Void, UnregisterCredentialDescriptionException> mCallback;
+
+ private UnregisterCredentialDescriptionTransport(Executor executor,
+ OutcomeReceiver<Void, UnregisterCredentialDescriptionException> callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onResponse() {
+ mCallback.onResult(null);
+ }
+
+ @Override
+ public void onError(String errorCode, String message) {
+ mExecutor.execute(
+ () -> mCallback.onError(new UnregisterCredentialDescriptionException(errorCode,
+ message)));
+ }
+ }
}
diff --git a/core/java/android/credentials/GetCredentialException.java b/core/java/android/credentials/GetCredentialException.java
index 478afff..720c53b 100644
--- a/core/java/android/credentials/GetCredentialException.java
+++ b/core/java/android/credentials/GetCredentialException.java
@@ -28,7 +28,7 @@
/**
* Represents an error encountered during the
- * {@link CredentialManager#executeGetCredential(GetCredentialRequest,
+ * {@link CredentialManager#getCredential(GetCredentialRequest,
* Activity, CancellationSignal, Executor, OutcomeReceiver)} operation.
*/
public class GetCredentialException extends Exception {
@@ -41,7 +41,7 @@
/**
* The error type value for when no credential is found available for the given {@link
- * CredentialManager#executeGetCredential(GetCredentialRequest, Activity, CancellationSignal,
+ * CredentialManager#getCredential(GetCredentialRequest, Activity, CancellationSignal,
* Executor, OutcomeReceiver)} request.
*/
@NonNull
diff --git a/core/java/android/credentials/GetCredentialOption.java b/core/java/android/credentials/GetCredentialOption.java
index 47731dd..55daf86 100644
--- a/core/java/android/credentials/GetCredentialOption.java
+++ b/core/java/android/credentials/GetCredentialOption.java
@@ -53,7 +53,7 @@
/**
* Determines whether the request must only be fulfilled by a system provider.
*/
- private final boolean mRequireSystemProvider;
+ private final boolean mIsSystemProviderRequired;
/**
* Returns the requested credential type.
@@ -91,8 +91,8 @@
* Returns true if the request must only be fulfilled by a system provider, and false
* otherwise.
*/
- public boolean requireSystemProvider() {
- return mRequireSystemProvider;
+ public boolean isSystemProviderRequired() {
+ return mIsSystemProviderRequired;
}
@Override
@@ -100,7 +100,7 @@
dest.writeString8(mType);
dest.writeBundle(mCredentialRetrievalData);
dest.writeBundle(mCandidateQueryData);
- dest.writeBoolean(mRequireSystemProvider);
+ dest.writeBoolean(mIsSystemProviderRequired);
}
@Override
@@ -114,7 +114,7 @@
+ "type=" + mType
+ ", requestData=" + mCredentialRetrievalData
+ ", candidateQueryData=" + mCandidateQueryData
- + ", requireSystemProvider=" + mRequireSystemProvider
+ + ", isSystemProviderRequired=" + mIsSystemProviderRequired
+ "}";
}
@@ -125,7 +125,7 @@
* @param credentialRetrievalData the request data
* @param candidateQueryData the partial request data that will be sent to the provider
* during the initial credential candidate query stage
- * @param requireSystemProvider whether the request must only be fulfilled by a system
+ * @param isSystemProviderRequired whether the request must only be fulfilled by a system
* provider
* @throws IllegalArgumentException If type is empty.
*/
@@ -133,20 +133,20 @@
@NonNull String type,
@NonNull Bundle credentialRetrievalData,
@NonNull Bundle candidateQueryData,
- boolean requireSystemProvider) {
+ boolean isSystemProviderRequired) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mCredentialRetrievalData = requireNonNull(credentialRetrievalData,
"requestData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
"candidateQueryData must not be null");
- mRequireSystemProvider = requireSystemProvider;
+ mIsSystemProviderRequired = isSystemProviderRequired;
}
private GetCredentialOption(@NonNull Parcel in) {
String type = in.readString8();
Bundle data = in.readBundle();
Bundle candidateQueryData = in.readBundle();
- boolean requireSystemProvider = in.readBoolean();
+ boolean isSystemProviderRequired = in.readBoolean();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
@@ -154,7 +154,7 @@
AnnotationValidations.validate(NonNull.class, null, mCredentialRetrievalData);
mCandidateQueryData = candidateQueryData;
AnnotationValidations.validate(NonNull.class, null, mCandidateQueryData);
- mRequireSystemProvider = requireSystemProvider;
+ mIsSystemProviderRequired = isSystemProviderRequired;
}
public static final @NonNull Parcelable.Creator<GetCredentialOption> CREATOR =
diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl
index c3ca03d..75b3d0c 100644
--- a/core/java/android/credentials/ICredentialManager.aidl
+++ b/core/java/android/credentials/ICredentialManager.aidl
@@ -21,10 +21,14 @@
import android.credentials.ClearCredentialStateRequest;
import android.credentials.CreateCredentialRequest;
import android.credentials.GetCredentialRequest;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.credentials.UnregisterCredentialDescriptionRequest;
import android.credentials.IClearCredentialStateCallback;
import android.credentials.ICreateCredentialCallback;
import android.credentials.IGetCredentialCallback;
import android.credentials.IListEnabledProvidersCallback;
+import android.credentials.IRegisterCredentialDescriptionCallback;
+import android.credentials.IUnregisterCredentialDescriptionCallback;
import android.credentials.ISetEnabledProvidersCallback;
import android.os.ICancellationSignal;
@@ -44,4 +48,9 @@
@nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
void setEnabledProviders(in List<String> providers, in int userId, in ISetEnabledProvidersCallback callback);
+
+ @nullable ICancellationSignal registerCredentialDescription(in RegisterCredentialDescriptionRequest request, in IRegisterCredentialDescriptionCallback callback, String callingPackage);
+
+ @nullable ICancellationSignal unRegisterCredentialDescription(in UnregisterCredentialDescriptionRequest request, in IUnregisterCredentialDescriptionCallback callback, String callingPackage);
}
+
diff --git a/core/java/android/credentials/IRegisterCredentialDescriptionCallback.aidl b/core/java/android/credentials/IRegisterCredentialDescriptionCallback.aidl
new file mode 100644
index 0000000..124a319
--- /dev/null
+++ b/core/java/android/credentials/IRegisterCredentialDescriptionCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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 android.credentials;
+
+/**
+ * Listener for an registerCredentialDescription request.
+ *
+ * @hide
+ */
+interface IRegisterCredentialDescriptionCallback {
+ oneway void onResponse();
+ oneway void onError(String errorCode, String message);
+}
\ No newline at end of file
diff --git a/core/java/android/credentials/IUnregisterCredentialDescriptionCallback.aidl b/core/java/android/credentials/IUnregisterCredentialDescriptionCallback.aidl
new file mode 100644
index 0000000..b30a12a
--- /dev/null
+++ b/core/java/android/credentials/IUnregisterCredentialDescriptionCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 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 android.credentials;
+
+/**
+ * Listener for an registerCredentialDescription request.
+ *
+ * @hide
+ */
+interface IUnregisterCredentialDescriptionCallback {
+ oneway void onResponse();
+ oneway void onError(String errorCode, String message);
+}
\ No newline at end of file
diff --git a/core/java/android/credentials/RegisterCredentialDescriptionException.java b/core/java/android/credentials/RegisterCredentialDescriptionException.java
new file mode 100644
index 0000000..3cf5a75
--- /dev/null
+++ b/core/java/android/credentials/RegisterCredentialDescriptionException.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 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 android.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Represents an error encountered during the {@link
+ * CredentialManager#registerCredentialDescription(RegisterCredentialDescriptionRequest,
+ * CancellationSignal, Executor, OutcomeReceiver)} operation.
+ *
+ * @hide
+ */
+public class RegisterCredentialDescriptionException extends Exception {
+
+ @NonNull public final String errorType;
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public RegisterCredentialDescriptionException(@NonNull String errorType,
+ @Nullable String message) {
+ this(errorType, message, null);
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public RegisterCredentialDescriptionException(
+ @NonNull String errorType, @Nullable String message, @Nullable Throwable cause) {
+ super(message, cause);
+ this.errorType =
+ Preconditions
+ .checkStringNotEmpty(errorType, "errorType must not be empty");
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public RegisterCredentialDescriptionException(@NonNull String errorType,
+ @Nullable Throwable cause) {
+ this(errorType, null, cause);
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public RegisterCredentialDescriptionException(@NonNull String errorType) {
+ this(errorType, null, null);
+ }
+}
diff --git a/core/java/android/credentials/RegisterCredentialDescriptionRequest.aidl b/core/java/android/credentials/RegisterCredentialDescriptionRequest.aidl
new file mode 100644
index 0000000..1d56728
--- /dev/null
+++ b/core/java/android/credentials/RegisterCredentialDescriptionRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.credentials;
+
+parcelable RegisterCredentialDescriptionRequest;
\ No newline at end of file
diff --git a/core/java/android/credentials/RegisterCredentialDescriptionRequest.java b/core/java/android/credentials/RegisterCredentialDescriptionRequest.java
new file mode 100644
index 0000000..de31279
--- /dev/null
+++ b/core/java/android/credentials/RegisterCredentialDescriptionRequest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 android.credentials;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * A request to register a {@link ComponentName} that contains an actively provisioned
+ * {@link Credential} represented by a {@link CredentialDescription}.
+ *
+ * @hide
+ */
+public final class RegisterCredentialDescriptionRequest implements Parcelable {
+
+ public static final String FLATTENED_REQUEST_STRING_KEY = "flattened_request_string";
+
+ @NonNull
+ private final List<CredentialDescription> mCredentialDescriptions;
+
+ public RegisterCredentialDescriptionRequest(
+ @NonNull CredentialDescription credentialDescription) {
+ mCredentialDescriptions = Arrays.asList(requireNonNull(credentialDescription));
+ }
+
+ public RegisterCredentialDescriptionRequest(
+ @NonNull List<CredentialDescription> credentialDescriptions) {
+ mCredentialDescriptions = new ArrayList<>(requireNonNull(credentialDescriptions));
+ }
+
+ private RegisterCredentialDescriptionRequest(@NonNull Parcel in) {
+ List<CredentialDescription> credentialDescriptions = new ArrayList<>();
+ in.readTypedList(credentialDescriptions, CredentialDescription.CREATOR);
+
+ mCredentialDescriptions = new ArrayList<>();
+ AnnotationValidations.validate(android.annotation.NonNull.class, null,
+ credentialDescriptions);
+ mCredentialDescriptions.addAll(credentialDescriptions);
+ }
+
+ public static final @NonNull Parcelable.Creator<RegisterCredentialDescriptionRequest> CREATOR =
+ new Parcelable.Creator<RegisterCredentialDescriptionRequest>() {
+ @Override
+ public RegisterCredentialDescriptionRequest createFromParcel(Parcel in) {
+ return new RegisterCredentialDescriptionRequest(in);
+ }
+
+ @Override
+ public RegisterCredentialDescriptionRequest[] newArray(int size) {
+ return new RegisterCredentialDescriptionRequest[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedList(mCredentialDescriptions, flags);
+ }
+
+ @NonNull
+ public List<CredentialDescription> getCredentialDescriptions() {
+ return mCredentialDescriptions;
+ }
+}
diff --git a/core/java/android/credentials/UnregisterCredentialDescriptionException.java b/core/java/android/credentials/UnregisterCredentialDescriptionException.java
new file mode 100644
index 0000000..0c786bd
--- /dev/null
+++ b/core/java/android/credentials/UnregisterCredentialDescriptionException.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 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 android.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Represents an error encountered during the {@link
+ * CredentialManager#registerCredentialDescription(RegisterCredentialDescriptionRequest,
+ * CancellationSignal, Executor, OutcomeReceiver)} operation.
+ *
+ * @hide
+ */
+public class UnregisterCredentialDescriptionException extends Exception {
+
+ @NonNull public final String errorType;
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public UnregisterCredentialDescriptionException(@NonNull String errorType,
+ @Nullable String message) {
+ this(errorType, message, null);
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public UnregisterCredentialDescriptionException(
+ @NonNull String errorType, @Nullable String message, @Nullable Throwable cause) {
+ super(message, cause);
+ this.errorType =
+ Preconditions
+ .checkStringNotEmpty(errorType, "errorType must not be empty");
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public UnregisterCredentialDescriptionException(@NonNull String errorType,
+ @Nullable Throwable cause) {
+ this(errorType, null, cause);
+ }
+
+ /**
+ * Constructs a {@link RegisterCredentialDescriptionException}.
+ *
+ * @throws IllegalArgumentException If errorType is empty.
+ */
+ public UnregisterCredentialDescriptionException(@NonNull String errorType) {
+ this(errorType, null, null);
+ }
+}
diff --git a/core/java/android/credentials/UnregisterCredentialDescriptionRequest.aidl b/core/java/android/credentials/UnregisterCredentialDescriptionRequest.aidl
new file mode 100644
index 0000000..e25f13c
--- /dev/null
+++ b/core/java/android/credentials/UnregisterCredentialDescriptionRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 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 android.credentials;
+
+parcelable UnregisterCredentialDescriptionRequest;
\ No newline at end of file
diff --git a/core/java/android/credentials/UnregisterCredentialDescriptionRequest.java b/core/java/android/credentials/UnregisterCredentialDescriptionRequest.java
new file mode 100644
index 0000000..f3454c1
--- /dev/null
+++ b/core/java/android/credentials/UnregisterCredentialDescriptionRequest.java
@@ -0,0 +1,81 @@
+/*
+ * 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 android.credentials;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+
+/**
+ * A request to unregister a {@link ComponentName} that contains an actively provisioned
+ * {@link Credential} represented by a {@link CredentialDescription}. *
+ *
+ * @hide
+ */
+public final class UnregisterCredentialDescriptionRequest implements Parcelable {
+
+ @NonNull
+ private final CredentialDescription mCredentialDescription;
+
+ public UnregisterCredentialDescriptionRequest(@NonNull CredentialDescription
+ credentialDescription) {
+ mCredentialDescription = requireNonNull(credentialDescription);
+ }
+
+ private UnregisterCredentialDescriptionRequest(@NonNull Parcel in) {
+ CredentialDescription credentialDescription =
+ CredentialDescription.CREATOR.createFromParcel(in);
+
+ mCredentialDescription = credentialDescription;
+ AnnotationValidations.validate(android.annotation.NonNull.class, null,
+ credentialDescription);
+ }
+
+ public static final @NonNull Parcelable.Creator<UnregisterCredentialDescriptionRequest>
+ CREATOR = new Parcelable.Creator<UnregisterCredentialDescriptionRequest>() {
+ @Override
+ public UnregisterCredentialDescriptionRequest createFromParcel(Parcel in) {
+ return new UnregisterCredentialDescriptionRequest(in);
+ }
+
+ @Override
+ public UnregisterCredentialDescriptionRequest[] newArray(int size) {
+ return new UnregisterCredentialDescriptionRequest[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mCredentialDescription.writeToParcel(dest, flags);
+ }
+
+ @NonNull
+ public CredentialDescription getCredentialDescription() {
+ return mCredentialDescription;
+ }
+}
diff --git a/core/java/android/credentials/ui/BaseDialogResult.java b/core/java/android/credentials/ui/BaseDialogResult.java
index cf5f036..5223314 100644
--- a/core/java/android/credentials/ui/BaseDialogResult.java
+++ b/core/java/android/credentials/ui/BaseDialogResult.java
@@ -16,6 +16,7 @@
package android.credentials.ui;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
@@ -25,6 +26,9 @@
import com.android.internal.util.AnnotationValidations;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Base dialog result data.
*
@@ -55,29 +59,27 @@
private static final String EXTRA_BASE_RESULT =
"android.credentials.ui.extra.BASE_RESULT";
+ /** @hide **/
+ @IntDef(prefix = {"RESULT_CODE_"}, value = {
+ RESULT_CODE_DIALOG_USER_CANCELED,
+ RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS,
+ RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResultCode {}
+
/** User intentionally canceled the dialog. */
- public static final int RESULT_CODE_DIALOG_CANCELED = 0;
- /**
- * User made a selection and the dialog finished. The user selection result is in the
- * {@code resultData}.
- */
- public static final int RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION = 1;
- /**
- * The user has acknowledged the consent page rendered for when they first used Credential
- * Manager on this device.
- */
- public static final int RESULT_CODE_CREDENTIAL_MANAGER_CONSENT_ACKNOWLEDGED = 2;
- /**
- * The user has acknowledged the consent page rendered for enabling a new provider.
- * This should only happen during the first time use. The provider info is in the
- * {@code resultData}.
- */
- public static final int RESULT_CODE_PROVIDER_ENABLED = 3;
+ public static final int RESULT_CODE_DIALOG_USER_CANCELED = 0;
/**
* The user has consented to switching to a new default provider. The provider info is in the
* {@code resultData}.
*/
- public static final int RESULT_CODE_DEFAULT_PROVIDER_CHANGED = 4;
+ public static final int RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS = 1;
+ /**
+ * User made a selection and the dialog finished. The user selection result is in the
+ * {@code resultData}.
+ */
+ public static final int RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION = 2;
@NonNull
private final IBinder mRequestToken;
diff --git a/core/java/android/credentials/ui/RequestInfo.java b/core/java/android/credentials/ui/RequestInfo.java
index e7b8dab..49ae9e9 100644
--- a/core/java/android/credentials/ui/RequestInfo.java
+++ b/core/java/android/credentials/ui/RequestInfo.java
@@ -48,9 +48,9 @@
/** Type value for any request that does not require UI. */
@NonNull public static final String TYPE_UNDEFINED = "android.credentials.ui.TYPE_UNDEFINED";
- /** Type value for an executeGetCredential request. */
+ /** Type value for a getCredential request. */
@NonNull public static final String TYPE_GET = "android.credentials.ui.TYPE_GET";
- /** Type value for an executeCreateCredential request. */
+ /** Type value for a createCredential request. */
@NonNull public static final String TYPE_CREATE = "android.credentials.ui.TYPE_CREATE";
/** @hide */
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 04a204a..b24b30e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -470,6 +470,16 @@
* @param isAcquiredGood whether the fingerprint image was good.
*/
public void onAcquired(boolean isAcquiredGood){ }
+
+ /**
+ * Called when a pointer down event has occurred.
+ */
+ public void onPointerDown(int sensorId){ }
+
+ /**
+ * Called when a pointer up event has occurred.
+ */
+ public void onPointerUp(int sensorId){ }
}
/**
@@ -1398,7 +1408,7 @@
if (mAuthenticationCallback != null) {
mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
}
- if (mEnrollmentCallback != null) {
+ if (mEnrollmentCallback != null && acquireInfo != FINGERPRINT_ACQUIRED_START) {
mEnrollmentCallback.onAcquired(acquireInfo == FINGERPRINT_ACQUIRED_GOOD);
}
final String msg = getAcquiredString(mContext, acquireInfo, vendorCode);
@@ -1454,17 +1464,24 @@
private void sendUdfpsPointerDown(int sensorId) {
if (mAuthenticationCallback == null) {
Slog.e(TAG, "sendUdfpsPointerDown, callback null");
- return;
+ } else {
+ mAuthenticationCallback.onUdfpsPointerDown(sensorId);
}
- mAuthenticationCallback.onUdfpsPointerDown(sensorId);
+
+ if (mEnrollmentCallback != null) {
+ mEnrollmentCallback.onPointerDown(sensorId);
+ }
}
private void sendUdfpsPointerUp(int sensorId) {
if (mAuthenticationCallback == null) {
Slog.e(TAG, "sendUdfpsPointerUp, callback null");
- return;
+ } else {
+ mAuthenticationCallback.onUdfpsPointerUp(sensorId);
}
- mAuthenticationCallback.onUdfpsPointerUp(sensorId);
+ if (mEnrollmentCallback != null) {
+ mEnrollmentCallback.onPointerUp(sensorId);
+ }
}
private void sendPowerPressed() {
diff --git a/core/java/android/hardware/input/HostUsiVersion.aidl b/core/java/android/hardware/input/HostUsiVersion.aidl
new file mode 100644
index 0000000..74f0ba8
--- /dev/null
+++ b/core/java/android/hardware/input/HostUsiVersion.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.hardware.input;
+
+parcelable HostUsiVersion;
diff --git a/core/java/android/hardware/input/HostUsiVersion.java b/core/java/android/hardware/input/HostUsiVersion.java
new file mode 100644
index 0000000..8f13d75
--- /dev/null
+++ b/core/java/android/hardware/input/HostUsiVersion.java
@@ -0,0 +1,204 @@
+/*
+ * 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 android.hardware.input;
+
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Provides information about the supported Universal Stylus Initiative (USI) version of the
+ * host device.
+ *
+ * This holds version information about the host device (e.g. the touchscreen/display), not
+ * the USI version of a stylus.
+ *
+ * @see InputManager#getHostUsiVersion(android.view.Display)
+ * @see <a href="https://universalstylus.org">Universal Stylus Initiative</a>
+ */
+@DataClass(genParcelable = true, genHiddenConstructor = true, genToString = true,
+ genEqualsHashCode = true)
+public final class HostUsiVersion implements Parcelable {
+ /**
+ * The major USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 2.
+ */
+ private final int mMajorVersion;
+
+ /**
+ * The minor USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 0.
+ */
+ private final int mMinorVersion;
+
+ /** @hide */
+ public boolean isValid() {
+ return mMajorVersion >= 0 && mMinorVersion >= 0;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/HostUsiVersion.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new HostUsiVersion.
+ *
+ * @param majorVersion
+ * The major USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 2.
+ * @param minorVersion
+ * The minor USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 0.
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public HostUsiVersion(
+ int majorVersion,
+ int minorVersion) {
+ this.mMajorVersion = majorVersion;
+ this.mMinorVersion = minorVersion;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The major USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 2.
+ */
+ @DataClass.Generated.Member
+ public int getMajorVersion() {
+ return mMajorVersion;
+ }
+
+ /**
+ * The minor USI version supported by the input device.
+ * For example, if the device supports USI 2.0, this will return 0.
+ */
+ @DataClass.Generated.Member
+ public int getMinorVersion() {
+ return mMinorVersion;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "HostUsiVersion { " +
+ "majorVersion = " + mMajorVersion + ", " +
+ "minorVersion = " + mMinorVersion +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(HostUsiVersion other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ HostUsiVersion that = (HostUsiVersion) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mMajorVersion == that.mMajorVersion
+ && mMinorVersion == that.mMinorVersion;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mMajorVersion;
+ _hash = 31 * _hash + mMinorVersion;
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(mMajorVersion);
+ dest.writeInt(mMinorVersion);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ HostUsiVersion(@android.annotation.NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int majorVersion = in.readInt();
+ int minorVersion = in.readInt();
+
+ this.mMajorVersion = majorVersion;
+ this.mMinorVersion = minorVersion;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @android.annotation.NonNull Parcelable.Creator<HostUsiVersion> CREATOR
+ = new Parcelable.Creator<HostUsiVersion>() {
+ @Override
+ public HostUsiVersion[] newArray(int size) {
+ return new HostUsiVersion[size];
+ }
+
+ @Override
+ public HostUsiVersion createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
+ return new HostUsiVersion(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1673884256908L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/input/HostUsiVersion.java",
+ inputSignatures = "private final int mMajorVersion\nprivate final int mMinorVersion\npublic boolean isValid()\nclass HostUsiVersion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genToString=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index fb201cf..dfd9054 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -56,8 +56,10 @@
import android.os.VibratorManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
+import android.util.DisplayUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.Display;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputMonitor;
@@ -69,6 +71,7 @@
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -99,6 +102,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final IInputManager mIm;
+ private final boolean mIsStylusPointerIconEnabled;
+
// Guarded by mInputDevicesLock
private final Object mInputDevicesLock = new Object();
private SparseArray<InputDevice> mInputDevices;
@@ -321,6 +326,15 @@
} catch (RemoteException ex) {
Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
}
+
+ // TODO(b/266013036): Pass a Context into InputManager constructor.
+ final Context context = ActivityThread.currentApplication();
+ if (context != null) {
+ mIsStylusPointerIconEnabled = context.getResources()
+ .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon);
+ } else {
+ mIsStylusPointerIconEnabled = false;
+ }
}
/**
@@ -1379,7 +1393,7 @@
* Changes the mouse pointer's icon shape into the specified id.
*
* @param iconId The id of the pointer graphic, as a value between
- * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_GRABBING}.
+ * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_HANDWRITING}.
*
* @hide
*/
@@ -1402,6 +1416,16 @@
}
/**
+ * Check if showing a {@link android.view.PointerIcon} for styluses is enabled.
+ *
+ * @return true if a pointer icon will be shown over the location of a
+ * stylus pointer, false if there is no pointer icon shown for styluses.
+ */
+ public boolean isStylusPointerIconEnabled() {
+ return mIsStylusPointerIconEnabled;
+ }
+
+ /**
* Request or release pointer capture.
* <p>
* When in capturing mode, the pointer icon disappears and all mouse events are dispatched to
@@ -1584,6 +1608,66 @@
}
}
+ /**
+ * Reports the version of the Universal Stylus Initiative (USI) protocol supported by the given
+ * display, if any.
+ *
+ * @return the USI version supported by the display, or null if the device does not support USI
+ * @see <a href="https://universalstylus.org">Universal Stylus Initiative</a>
+ */
+ @Nullable
+ public HostUsiVersion getHostUsiVersion(@NonNull Display display) {
+ Objects.requireNonNull(display, "display should not be null");
+
+ // Return the first valid USI version reported by any input device associated with
+ // the display.
+ synchronized (mInputDevicesLock) {
+ populateInputDevicesLocked();
+
+ for (int i = 0; i < mInputDevices.size(); i++) {
+ final InputDevice device = getInputDevice(mInputDevices.keyAt(i));
+ if (device != null && device.getAssociatedDisplayId() == display.getDisplayId()) {
+ if (device.getHostUsiVersion() != null) {
+ return device.getHostUsiVersion();
+ }
+ }
+ }
+ }
+
+ // If there are no input devices that report a valid USI version, see if there is a config
+ // that specifies the USI version for the display. This is to handle cases where the USI
+ // input device is not registered by the kernel/driver all the time.
+ return findConfigUsiVersionForDisplay(display);
+ }
+
+ private HostUsiVersion findConfigUsiVersionForDisplay(@NonNull Display display) {
+ final Context context = Objects.requireNonNull(ActivityThread.currentApplication());
+ final String[] displayUniqueIds = context.getResources().getStringArray(
+ R.array.config_displayUniqueIdArray);
+ final int index;
+ if (displayUniqueIds.length == 0 && display.getDisplayId() == context.getDisplayId()) {
+ index = 0;
+ } else {
+ index = DisplayUtils.getDisplayUniqueIdConfigIndex(context.getResources(),
+ display.getUniqueId());
+ }
+
+ final String[] versions = context.getResources().getStringArray(
+ R.array.config_displayUsiVersionArray);
+ if (index < 0 || index >= versions.length) {
+ return null;
+ }
+ final String version = versions[index];
+ if (version == null || version.isEmpty()) {
+ return null;
+ }
+ final String[] majorMinor = version.split("\\.");
+ if (majorMinor.length != 2) {
+ throw new IllegalStateException("Failed to parse USI version: " + version);
+ }
+ return new HostUsiVersion(Integer.parseInt(majorMinor[0]), Integer.parseInt(majorMinor[1]));
+ }
+
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index ac23af4..01ce7b9 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -995,6 +995,51 @@
}
/**
+ * Puts the Context Hub in test mode.
+ *
+ * The purpose of this API is to make testing CHRE/Context Hub more
+ * predictable and robust. This temporarily unloads all
+ * nanoapps.
+ *
+ * Note that this API must not cause CHRE/Context Hub to behave differently
+ * in test compared to production.
+ *
+ * @return true if the enable test mode operation succeeded.
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @NonNull public boolean enableTestMode() {
+ try {
+ return mService.setTestMode(true);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Puts the Context Hub out of test mode.
+ *
+ * This API will undo any previously made enableTestMode() calls.
+ * After this API is called, it should restore the state of the system
+ * to the normal/production mode before any enableTestMode() call was
+ * made. If the enableTestMode() call unloaded any nanoapps
+ * to enter test mode, it should reload those nanoapps in this API call.
+ *
+ * @return true if the disable operation succeeded.
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ @NonNull public boolean disableTestMode() {
+ try {
+ return mService.setTestMode(false);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Unregister a callback for receive messages from the context hub.
*
* @see Callback
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index 490267f..11f30461 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -113,4 +113,8 @@
// Queries for a list of preloaded nanoapps
@EnforcePermission("ACCESS_CONTEXT_HUB")
long[] getPreloadedNanoAppIds(in ContextHubInfo hubInfo);
+
+ // Enables or disables test mode
+ @EnforcePermission("ACCESS_CONTEXT_HUB")
+ boolean setTestMode(in boolean enable);
}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index ed6a88f..d55367f 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -223,13 +223,11 @@
final SomeArgs args = (SomeArgs) msg.obj;
final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
if (isValid(inputMethod, target, "DO_SHOW_SOFT_INPUT")) {
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
inputMethod.showSoftInputWithToken(
msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1, statsToken);
} else {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
}
args.recycle();
return;
@@ -238,13 +236,11 @@
final SomeArgs args = (SomeArgs) msg.obj;
final ImeTracker.Token statsToken = (ImeTracker.Token) args.arg3;
if (isValid(inputMethod, target, "DO_HIDE_SOFT_INPUT")) {
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2,
(IBinder) args.arg1, statsToken);
} else {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_IME_WRAPPER_DISPATCH);
}
args.recycle();
return;
@@ -432,7 +428,7 @@
@Override
public void showSoftInput(IBinder showInputToken, @Nullable ImeTracker.Token statsToken,
int flags, ResultReceiver resultReceiver) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_SHOW_SOFT_INPUT,
flags, showInputToken, resultReceiver, statsToken));
}
@@ -441,7 +437,7 @@
@Override
public void hideSoftInput(IBinder hideInputToken, @Nullable ImeTracker.Token statsToken,
int flags, ResultReceiver resultReceiver) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_IME_WRAPPER);
mCaller.executeOrSendMessage(mCaller.obtainMessageIOOO(DO_HIDE_SOFT_INPUT,
flags, hideInputToken, resultReceiver, statsToken));
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ee9d8a4..872414a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -896,8 +896,7 @@
@MainThread
@Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
- ImeTracker.forLogging().onProgress(
- mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
+ ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_HIDE_SOFT_INPUT);
if (DEBUG) Log.v(TAG, "hideSoftInput()");
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
&& !mSystemCallingHideSoftInput) {
@@ -951,8 +950,7 @@
@MainThread
@Override
public void showSoftInput(int flags, ResultReceiver resultReceiver) {
- ImeTracker.forLogging().onProgress(
- mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
+ ImeTracker.get().onProgress(mCurStatsToken, ImeTracker.PHASE_IME_SHOW_SOFT_INPUT);
if (DEBUG) Log.v(TAG, "showSoftInput()");
// TODO(b/148086656): Disallow IME developers from calling InputMethodImpl methods.
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
@@ -968,11 +966,11 @@
null /* icProto */);
final boolean wasVisible = isInputViewShown();
if (dispatchOnShowInputRequested(flags, false)) {
- ImeTracker.forLogging().onProgress(mCurStatsToken,
+ ImeTracker.get().onProgress(mCurStatsToken,
ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
showWindow(true);
} else {
- ImeTracker.forLogging().onFailed(mCurStatsToken,
+ ImeTracker.get().onFailed(mCurStatsToken,
ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
}
setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
@@ -2981,7 +2979,7 @@
ImeTracing.getInstance().triggerServiceDump(
"InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper,
null /* icProto */);
- ImeTracker.forLogging().onProgress(mCurStatsToken,
+ ImeTracker.get().onProgress(mCurStatsToken,
ImeTracker.PHASE_IME_APPLY_VISIBILITY_INSETS_CONSUMER);
mPrivOps.applyImeVisibilityAsync(setVisible
? mCurShowInputToken : mCurHideInputToken, setVisible, mCurStatsToken);
diff --git a/core/java/android/nfc/BeamShareData.aidl b/core/java/android/nfc/BeamShareData.aidl
new file mode 100644
index 0000000..a47e240
--- /dev/null
+++ b/core/java/android/nfc/BeamShareData.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.nfc;
+
+parcelable BeamShareData;
diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java
new file mode 100644
index 0000000..6a40f98
--- /dev/null
+++ b/core/java/android/nfc/BeamShareData.java
@@ -0,0 +1,67 @@
+package android.nfc;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+/**
+ * Class to IPC data to be shared over Android Beam.
+ * Allows bundling NdefMessage, Uris and flags in a single
+ * IPC call. This is important as we want to reduce the
+ * amount of IPC calls at "touch time".
+ * @hide
+ */
+public final class BeamShareData implements Parcelable {
+ public final NdefMessage ndefMessage;
+ public final Uri[] uris;
+ public final UserHandle userHandle;
+ public final int flags;
+
+ public BeamShareData(NdefMessage msg, Uri[] uris, UserHandle userHandle, int flags) {
+ this.ndefMessage = msg;
+ this.uris = uris;
+ this.userHandle = userHandle;
+ this.flags = flags;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ int urisLength = (uris != null) ? uris.length : 0;
+ dest.writeParcelable(ndefMessage, 0);
+ dest.writeInt(urisLength);
+ if (urisLength > 0) {
+ dest.writeTypedArray(uris, 0);
+ }
+ dest.writeParcelable(userHandle, 0);
+ dest.writeInt(this.flags);
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<BeamShareData> CREATOR =
+ new Parcelable.Creator<BeamShareData>() {
+ @Override
+ public BeamShareData createFromParcel(Parcel source) {
+ Uri[] uris = null;
+ NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader(), android.nfc.NdefMessage.class);
+ int numUris = source.readInt();
+ if (numUris > 0) {
+ uris = new Uri[numUris];
+ source.readTypedArray(uris, Uri.CREATOR);
+ }
+ UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class);
+ int flags = source.readInt();
+
+ return new BeamShareData(msg, uris, userHandle, flags);
+ }
+
+ @Override
+ public BeamShareData[] newArray(int size) {
+ return new BeamShareData[size];
+ }
+ };
+}
diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl
index b06bf06..133146d 100644
--- a/core/java/android/nfc/IAppCallback.aidl
+++ b/core/java/android/nfc/IAppCallback.aidl
@@ -16,6 +16,7 @@
package android.nfc;
+import android.nfc.BeamShareData;
import android.nfc.Tag;
/**
@@ -23,5 +24,7 @@
*/
interface IAppCallback
{
+ BeamShareData createBeamShareData(byte peerLlcpVersion);
+ oneway void onNdefPushComplete(byte peerLlcpVersion);
oneway void onTagDiscovered(in Tag tag);
}
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index f6aa4b4..8a30ef4 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.IntentFilter;
+import android.nfc.BeamShareData;
import android.nfc.NdefMessage;
import android.nfc.Tag;
import android.nfc.TechListParcel;
@@ -46,18 +47,24 @@
int getState();
boolean disable(boolean saveState);
boolean enable();
+ boolean enableNdefPush();
+ boolean disableNdefPush();
+ boolean isNdefPushEnabled();
void pausePolling(int timeoutInMs);
void resumePolling();
void setForegroundDispatch(in PendingIntent intent,
in IntentFilter[] filters, in TechListParcel techLists);
void setAppCallback(in IAppCallback callback);
+ oneway void invokeBeam();
+ oneway void invokeBeamInternal(in BeamShareData shareData);
boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback);
void dispatch(in Tag tag);
void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras);
+ void setP2pModes(int initatorModes, int targetModes);
void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
@@ -73,4 +80,10 @@
boolean isControllerAlwaysOnSupported();
void registerControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
void unregisterControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ boolean isTagIntentAppPreferenceSupported();
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ Map getTagIntentAppPreferenceForUser(int userId);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
+ int setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow);
}
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 8d75cac..911aaf3 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -19,6 +19,9 @@
import android.app.Activity;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ContentProvider;
+import android.content.Intent;
+import android.net.Uri;
import android.nfc.NfcAdapter.ReaderCallback;
import android.os.Binder;
import android.os.Bundle;
@@ -107,8 +110,14 @@
class NfcActivityState {
boolean resumed = false;
Activity activity;
- NfcAdapter.ReaderCallback readerCallback = null;
+ NdefMessage ndefMessage = null; // static NDEF message
+ NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null;
+ NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
+ NfcAdapter.CreateBeamUrisCallback uriCallback = null;
+ Uri[] uris = null;
+ int flags = 0;
int readerModeFlags = 0;
+ NfcAdapter.ReaderCallback readerCallback = null;
Bundle readerModeExtras = null;
Binder token;
@@ -128,16 +137,24 @@
unregisterApplication(activity.getApplication());
resumed = false;
activity = null;
- readerCallback = null;
+ ndefMessage = null;
+ ndefMessageCallback = null;
+ onNdefPushCompleteCallback = null;
+ uriCallback = null;
+ uris = null;
readerModeFlags = 0;
- readerModeExtras = null;
token = null;
}
@Override
public String toString() {
- StringBuilder s = new StringBuilder("[");
- s.append(readerCallback);
- s.append("]");
+ StringBuilder s = new StringBuilder("[").append(" ");
+ s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" ");
+ s.append(uriCallback).append(" ");
+ if (uris != null) {
+ for (Uri uri : uris) {
+ s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]");
+ }
+ }
return s.toString();
}
}
@@ -228,6 +245,92 @@
}
}
+ public void setNdefPushContentUri(Activity activity, Uri[] uris) {
+ boolean isResumed;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.uris = uris;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ // requestNfcServiceCallback() verifies permission also
+ requestNfcServiceCallback();
+ } else {
+ // Crash API calls early in case NFC permission is missing
+ verifyNfcPermission();
+ }
+ }
+
+
+ public void setNdefPushContentUriCallback(Activity activity,
+ NfcAdapter.CreateBeamUrisCallback callback) {
+ boolean isResumed;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.uriCallback = callback;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ // requestNfcServiceCallback() verifies permission also
+ requestNfcServiceCallback();
+ } else {
+ // Crash API calls early in case NFC permission is missing
+ verifyNfcPermission();
+ }
+ }
+
+ public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) {
+ boolean isResumed;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.ndefMessage = message;
+ state.flags = flags;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ // requestNfcServiceCallback() verifies permission also
+ requestNfcServiceCallback();
+ } else {
+ // Crash API calls early in case NFC permission is missing
+ verifyNfcPermission();
+ }
+ }
+
+ public void setNdefPushMessageCallback(Activity activity,
+ NfcAdapter.CreateNdefMessageCallback callback, int flags) {
+ boolean isResumed;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.ndefMessageCallback = callback;
+ state.flags = flags;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ // requestNfcServiceCallback() verifies permission also
+ requestNfcServiceCallback();
+ } else {
+ // Crash API calls early in case NFC permission is missing
+ verifyNfcPermission();
+ }
+ }
+
+ public void setOnNdefPushCompleteCallback(Activity activity,
+ NfcAdapter.OnNdefPushCompleteCallback callback) {
+ boolean isResumed;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.onNdefPushCompleteCallback = callback;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ // requestNfcServiceCallback() verifies permission also
+ requestNfcServiceCallback();
+ } else {
+ // Crash API calls early in case NFC permission is missing
+ verifyNfcPermission();
+ }
+ }
+
/**
* Request or unrequest NFC service callbacks.
* Makes IPC call - do not hold lock.
@@ -248,6 +351,86 @@
}
}
+ /** Callback from NFC service, usually on binder thread */
+ @Override
+ public BeamShareData createBeamShareData(byte peerLlcpVersion) {
+ NfcAdapter.CreateNdefMessageCallback ndefCallback;
+ NfcAdapter.CreateBeamUrisCallback urisCallback;
+ NdefMessage message;
+ Activity activity;
+ Uri[] uris;
+ int flags;
+ NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = findResumedActivityState();
+ if (state == null) return null;
+
+ ndefCallback = state.ndefMessageCallback;
+ urisCallback = state.uriCallback;
+ message = state.ndefMessage;
+ uris = state.uris;
+ flags = state.flags;
+ activity = state.activity;
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ // Make callbacks without lock
+ if (ndefCallback != null) {
+ message = ndefCallback.createNdefMessage(event);
+ }
+ if (urisCallback != null) {
+ uris = urisCallback.createBeamUris(event);
+ if (uris != null) {
+ ArrayList<Uri> validUris = new ArrayList<Uri>();
+ for (Uri uri : uris) {
+ if (uri == null) {
+ Log.e(TAG, "Uri not allowed to be null.");
+ continue;
+ }
+ String scheme = uri.getScheme();
+ if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
+ !scheme.equalsIgnoreCase("content"))) {
+ Log.e(TAG, "Uri needs to have " +
+ "either scheme file or scheme content");
+ continue;
+ }
+ uri = ContentProvider.maybeAddUserId(uri, activity.getUserId());
+ validUris.add(uri);
+ }
+
+ uris = validUris.toArray(new Uri[validUris.size()]);
+ }
+ }
+ if (uris != null && uris.length > 0) {
+ for (Uri uri : uris) {
+ // Grant the NFC process permission to read these URIs
+ activity.grantUriPermission("com.android.nfc", uri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return new BeamShareData(message, uris, activity.getUser(), flags);
+ }
+
+ /** Callback from NFC service, usually on binder thread */
+ @Override
+ public void onNdefPushComplete(byte peerLlcpVersion) {
+ NfcAdapter.OnNdefPushCompleteCallback callback;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = findResumedActivityState();
+ if (state == null) return;
+
+ callback = state.onNdefPushCompleteCallback;
+ }
+ NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
+ // Make callback without lock
+ if (callback != null) {
+ callback.onNdefPushComplete(event);
+ }
+ }
+
@Override
public void onTagDiscovered(Tag tag) throws RemoteException {
NfcAdapter.ReaderCallback callback;
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index c4b3c22..a980158 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -17,12 +17,14 @@
package android.nfc;
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.OnActivityPausedListener;
@@ -46,9 +48,14 @@
import android.util.Log;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -338,10 +345,7 @@
*/
public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
- /**
- * @hide
- * @removed
- */
+ /** @hide */
@SystemApi
public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
@@ -374,9 +378,49 @@
public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC =
"android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
+ /**
+ * The requested app is correctly added to the Tag intent app preference.
+ *
+ * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
+ * @hide
+ */
+ @SystemApi
+ public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0;
+
+ /**
+ * The requested app is not installed on the device.
+ *
+ * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
+ * @hide
+ */
+ @SystemApi
+ public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1;
+
+ /**
+ * The NfcService is not available.
+ *
+ * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
+ * @hide
+ */
+ @SystemApi
+ public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2;
+
+ /**
+ * Possible response codes from {@link #setTagIntentAppPreferenceForUser}.
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "TAG_INTENT_APP_PREF_RESULT" }, value = {
+ TAG_INTENT_APP_PREF_RESULT_SUCCESS,
+ TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND,
+ TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TagIntentAppPreferenceResult {}
+
// Guarded by NfcAdapter.class
static boolean sIsInitialized = false;
static boolean sHasNfcFeature;
+ static boolean sHasBeamFeature;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
@@ -440,7 +484,7 @@
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
* @see #setOnNdefPushCompleteCallback
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -466,7 +510,7 @@
* content currently visible to the user. Alternatively, you can call {@link
* #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
* same data.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -496,7 +540,7 @@
/**
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -528,6 +572,26 @@
}
/**
+ * Helper to check if this device has FEATURE_NFC_BEAM, but without using
+ * a context.
+ * Equivalent to
+ * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)
+ */
+ private static boolean hasBeamFeature() {
+ IPackageManager pm = ActivityThread.getPackageManager();
+ if (pm == null) {
+ Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature");
+ return false;
+ }
+ try {
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e);
+ return false;
+ }
+ }
+
+ /**
* Helper to check if this device has FEATURE_NFC, but without using
* a context.
* Equivalent to
@@ -606,6 +670,7 @@
public static synchronized NfcAdapter getNfcAdapter(Context context) {
if (!sIsInitialized) {
sHasNfcFeature = hasNfcFeature();
+ sHasBeamFeature = hasBeamFeature();
boolean hasHceFeature = hasNfcHceFeature();
/* is this device meant to have NFC */
if (!sHasNfcFeature && !hasHceFeature) {
@@ -1098,7 +1163,7 @@
* @param uris an array of Uri(s) to push over Android Beam
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1107,7 +1172,26 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ if (uris != null) {
+ for (Uri uri : uris) {
+ if (uri == null) throw new NullPointerException("Uri not " +
+ "allowed to be null");
+ String scheme = uri.getScheme();
+ if (scheme == null || (!scheme.equalsIgnoreCase("file") &&
+ !scheme.equalsIgnoreCase("content"))) {
+ throw new IllegalArgumentException("URI needs to have " +
+ "either scheme file or scheme content");
+ }
+ }
+ }
+ mNfcActivityManager.setNdefPushContentUri(activity, uris);
}
/**
@@ -1167,7 +1251,7 @@
* @param callback callback, or null to disable
* @param activity activity for which the Uri(s) will be pushed
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1176,7 +1260,14 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushContentUriCallback(activity, callback);
}
/**
@@ -1250,7 +1341,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1260,12 +1351,36 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
+ }
+ int targetSdkVersion = getSdkVersion();
+ try {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessage(activity, message, 0);
+ for (Activity a : activities) {
+ if (a == null) {
+ throw new NullPointerException("activities cannot contain null");
+ }
+ mNfcActivityManager.setNdefPushMessage(a, message, 0);
+ }
+ } catch (IllegalStateException e) {
+ if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ // Less strict on old applications - just log the error
+ Log.e(TAG, "Cannot call API with Activity that has already " +
+ "been destroyed", e);
+ } else {
+ // Prevent new applications from making this mistake, re-throw
+ throw(e);
+ }
}
}
/**
* @hide
- * @removed
*/
@SystemApi
public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
@@ -1274,6 +1389,10 @@
throw new UnsupportedOperationException();
}
}
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessage(activity, message, flags);
}
/**
@@ -1341,7 +1460,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1351,7 +1470,44 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
+ int targetSdkVersion = getSdkVersion();
+ try {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessageCallback(activity, callback, 0);
+ for (Activity a : activities) {
+ if (a == null) {
+ throw new NullPointerException("activities cannot contain null");
+ }
+ mNfcActivityManager.setNdefPushMessageCallback(a, callback, 0);
+ }
+ } catch (IllegalStateException e) {
+ if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ // Less strict on old applications - just log the error
+ Log.e(TAG, "Cannot call API with Activity that has already " +
+ "been destroyed", e);
+ } else {
+ // Prevent new applications from making this mistake, re-throw
+ throw(e);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
+ int flags) {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setNdefPushMessageCallback(activity, callback, flags);
}
/**
@@ -1391,7 +1547,7 @@
* to only register one at a time, and to do so in that activity's
* {@link Activity#onCreate}
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1401,6 +1557,31 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
+ }
+ int targetSdkVersion = getSdkVersion();
+ try {
+ if (activity == null) {
+ throw new NullPointerException("activity cannot be null");
+ }
+ mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callback);
+ for (Activity a : activities) {
+ if (a == null) {
+ throw new NullPointerException("activities cannot contain null");
+ }
+ mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
+ }
+ } catch (IllegalStateException e) {
+ if (targetSdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ // Less strict on old applications - just log the error
+ Log.e(TAG, "Cannot call API with Activity that has already " +
+ "been destroyed", e);
+ } else {
+ // Prevent new applications from making this mistake, re-throw
+ throw(e);
+ }
}
}
@@ -1583,7 +1764,7 @@
* @param activity the current foreground Activity that has registered data to share
* @return whether the Beam animation was successfully invoked
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
@@ -1592,8 +1773,37 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return false;
+ }
}
- return false;
+ if (activity == null) {
+ throw new NullPointerException("activity may not be null.");
+ }
+ enforceResumed(activity);
+ try {
+ sService.invokeBeam();
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "invokeBeam: NFC process has died.");
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public boolean invokeBeam(BeamShareData shareData) {
+ try {
+ Log.e(TAG, "invokeBeamInternal()");
+ sService.invokeBeamInternal(shareData);
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "invokeBeam: NFC process has died.");
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
}
/**
@@ -1619,9 +1829,9 @@
*
* @param activity foreground activity
* @param message a NDEF Message to push over NFC
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
- * @removed this feature is removed. File sharing can work using other technology like
- * Bluetooth.
+ * @throws IllegalStateException if the activity is not currently in the foreground
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated use {@link #setNdefPushMessage} instead
*/
@Deprecated
public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
@@ -1629,7 +1839,15 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
+ if (activity == null || message == null) {
+ throw new NullPointerException();
+ }
+ enforceResumed(activity);
+ mNfcActivityManager.setNdefPushMessage(activity, message, 0);
}
/**
@@ -1648,9 +1866,9 @@
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param activity the Foreground activity
- * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
- * @removed this feature is removed. File sharing can work using other technology like
- * Bluetooth.
+ * @throws IllegalStateException if the Activity has already been paused
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
+ * @deprecated use {@link #setNdefPushMessage} instead
*/
@Deprecated
public void disableForegroundNdefPush(Activity activity) {
@@ -1658,7 +1876,17 @@
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return;
+ }
}
+ if (activity == null) {
+ throw new NullPointerException();
+ }
+ enforceResumed(activity);
+ mNfcActivityManager.setNdefPushMessage(activity, null, 0);
+ mNfcActivityManager.setNdefPushMessageCallback(activity, null, 0);
+ mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
}
/**
@@ -1783,24 +2011,40 @@
* Enable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
- * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean enableNdefPush() {
- return false;
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.enableNdefPush();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
}
/**
* Disable NDEF Push feature.
* <p>This API is for the Settings application.
* @hide
- * @removed
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
public boolean disableNdefPush() {
- return false;
+ synchronized (NfcAdapter.class) {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ }
+ try {
+ return sService.disableNdefPush();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
}
/**
@@ -1826,17 +2070,26 @@
* @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
* @return true if NDEF Push feature is enabled
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
- * @removed this feature is removed. File sharing can work using other technology like
+ * @deprecated this feature is deprecated. File sharing can work using other technology like
* Bluetooth.
*/
@java.lang.Deprecated
+
public boolean isNdefPushEnabled() {
synchronized (NfcAdapter.class) {
if (!sHasNfcFeature) {
throw new UnsupportedOperationException();
}
+ if (!sHasBeamFeature) {
+ return false;
+ }
}
- return false;
+ try {
+ return sService.isNdefPushEnabled();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return false;
+ }
}
/**
@@ -1927,6 +2180,17 @@
}
/**
+ * @hide
+ */
+ public void setP2pModes(int initiatorModes, int targetModes) {
+ try {
+ sService.setP2pModes(initiatorModes, targetModes);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
* Registers a new NFC unlock handler with the NFC service.
*
* <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
@@ -2190,4 +2454,133 @@
@NonNull ControllerAlwaysOnListener listener) {
mControllerAlwaysOnListener.unregister(listener);
}
+
+
+ /**
+ * Sets whether we dispatch NFC Tag intents to the package.
+ *
+ * <p>{@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
+ * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
+ * disallowed.
+ * <p>An app is added to the preference list with the allowed flag set to {@code true}
+ * when a Tag intent is dispatched to the package for the first time. This API is called
+ * by settings to note that the user wants to change this default preference.
+ *
+ * @param userId the user to whom this package name will belong to
+ * @param pkg the full name (i.e. com.google.android.tag) of the package that will be added to
+ * the preference list
+ * @param allow {@code true} to allow dispatching Tag intents to the package's activity,
+ * {@code false} otherwise
+ * @return the {@link #TagIntentAppPreferenceResult} value
+ * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
+ * {@code false}
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @TagIntentAppPreferenceResult
+ public int setTagIntentAppPreferenceForUser(@UserIdInt int userId,
+ @NonNull String pkg, boolean allow) {
+ Objects.requireNonNull(pkg, "pkg cannot be null");
+ if (!isTagIntentAppPreferenceSupported()) {
+ Log.e(TAG, "TagIntentAppPreference is not supported");
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ try {
+ return sService.setTagIntentAppPreferenceForUser(userId, pkg, allow);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE;
+ }
+ }
+
+
+ /**
+ * Get the Tag dispatch preference list of the UserId.
+ *
+ * <p>This returns a mapping of package names for this user id to whether we dispatch Tag
+ * intents to the package. {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
+ * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
+ * disallowed.
+ *
+ * @param userId the user to whom this preference list will belong to
+ * @return a map of the UserId which indicates the mapping from package name to
+ * boolean(allow status), otherwise return an empty map
+ * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
+ * {@code false}
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @NonNull
+ public Map<String, Boolean> getTagIntentAppPreferenceForUser(@UserIdInt int userId) {
+ if (!isTagIntentAppPreferenceSupported()) {
+ Log.e(TAG, "TagIntentAppPreference is not supported");
+ throw new UnsupportedOperationException();
+ }
+ try {
+ Map<String, Boolean> result = (Map<String, Boolean>) sService
+ .getTagIntentAppPreferenceForUser(userId);
+ return result;
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return Collections.emptyMap();
+ }
+ try {
+ Map<String, Boolean> result = (Map<String, Boolean>) sService
+ .getTagIntentAppPreferenceForUser(userId);
+ return result;
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Checks if the device supports Tag application preference.
+ *
+ * @return {@code true} if the device supports Tag application preference, {@code false}
+ * otherwise
+ * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ public boolean isTagIntentAppPreferenceSupported() {
+ if (!sHasNfcFeature) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return sService.isTagIntentAppPreferenceSupported();
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ // Try one more time
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ return false;
+ }
+ try {
+ return sService.isTagIntentAppPreferenceSupported();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover NFC Service.");
+ }
+ return false;
+ }
+ }
}
diff --git a/core/java/android/nfc/OWNERS b/core/java/android/nfc/OWNERS
index 6aaf039..9a2e446 100644
--- a/core/java/android/nfc/OWNERS
+++ b/core/java/android/nfc/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 48448
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
diff --git a/core/java/android/nfc/cardemulation/OWNERS b/core/java/android/nfc/cardemulation/OWNERS
index 6aaf039..9a2e446 100644
--- a/core/java/android/nfc/cardemulation/OWNERS
+++ b/core/java/android/nfc/cardemulation/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 48448
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
diff --git a/core/java/android/nfc/dta/OWNERS b/core/java/android/nfc/dta/OWNERS
index 6aaf039..9a2e446 100644
--- a/core/java/android/nfc/dta/OWNERS
+++ b/core/java/android/nfc/dta/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 48448
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
diff --git a/core/java/android/nfc/tech/OWNERS b/core/java/android/nfc/tech/OWNERS
index 6aaf039..9a2e446 100644
--- a/core/java/android/nfc/tech/OWNERS
+++ b/core/java/android/nfc/tech/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 48448
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 547d406..083b4f6 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2904,6 +2904,15 @@
public abstract long getMobileRadioEnergyConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the phone calls, derived from on device
+ * power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getPhoneEnergyConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
* device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 32773a0..249f486 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -754,9 +754,12 @@
* PackageManager.setComponentEnabledSetting} will now throw an
* IllegalArgumentException if the given component class name does not
* exist in the application's manifest.
- * <li> {@code NfcAdapter.setNdefPushMessage},
- * {@code NfcAdapter.setNdefPushMessageCallback} and
- * {@code NfcAdapter.setOnNdefPushCompleteCallback} will throw
+ * <li> {@link android.nfc.NfcAdapter#setNdefPushMessage
+ * NfcAdapter.setNdefPushMessage},
+ * {@link android.nfc.NfcAdapter#setNdefPushMessageCallback
+ * NfcAdapter.setNdefPushMessageCallback} and
+ * {@link android.nfc.NfcAdapter#setOnNdefPushCompleteCallback
+ * NfcAdapter.setOnNdefPushCompleteCallback} will throw
* IllegalStateException if called after the Activity has been destroyed.
* <li> Accessibility services must require the new
* {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission or
diff --git a/core/java/android/os/IncidentManager.java b/core/java/android/os/IncidentManager.java
index a543a2d..b97993a 100644
--- a/core/java/android/os/IncidentManager.java
+++ b/core/java/android/os/IncidentManager.java
@@ -119,6 +119,19 @@
public static final int FLAG_CONFIRMATION_DIALOG = 0x1;
/**
+ * Flag marking whether corresponding pending report allows consentless bugreport.
+ */
+ public static final int FLAG_ALLOW_CONSENTLESS_BUGREPORT = 0x2;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+ FLAG_CONFIRMATION_DIALOG,
+ FLAG_ALLOW_CONSENTLESS_BUGREPORT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PendingReportFlags {}
+
+ /**
* Flag marking fields and incident reports than can be taken
* off the device only via adb.
*/
@@ -220,8 +233,9 @@
/**
* Get the flags requested for this pending report.
*
- * @see #FLAG_CONFIRMATION_DIALOG
+ * @see PendingReportFlags
*/
+ @PendingReportFlags
public int getFlags() {
return mFlags;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 62d8fb2..9a25c70 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -65,7 +65,6 @@
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
-import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.FrameworkStatsLog;
import java.io.IOException;
@@ -2111,17 +2110,6 @@
}
/**
- * @hide
- * @return Whether the device is running with split system user. It means the system user and
- * primary user are two separate users. Previously system user and primary user are combined as
- * a single owner user. see @link {android.os.UserHandle#USER_OWNER}
- */
- @TestApi
- public static boolean isSplitSystemUser() {
- return RoSystemProperties.FW_SYSTEM_USER_SPLIT;
- }
-
- /**
* @return Whether guest user is always ephemeral
* @hide
*/
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index fa6efa8..4366c28 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -28,6 +28,7 @@
import android.hardware.vibrator.V1_0.EffectStrength;
import android.hardware.vibrator.V1_3.Effect;
import android.net.Uri;
+import android.os.Vibrator;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.RampSegment;
@@ -515,6 +516,16 @@
public abstract long getDuration();
/**
+ * Checks if a given {@link Vibrator} can play this effect as intended.
+ *
+ * <p>See @link Vibrator#areVibrationFeaturesSupported(VibrationEffect)} for more information
+ * about what counts as supported by a vibrator, and what counts as not.
+ *
+ * @hide
+ */
+ public abstract boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator);
+
+ /**
* Returns true if this effect could represent a touch haptic feedback.
*
* <p>It is strongly recommended that an instance of {@link VibrationAttributes} is specified
@@ -758,6 +769,17 @@
/** @hide */
@Override
+ public boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator) {
+ for (VibrationEffectSegment segment : mSegments) {
+ if (!segment.areVibrationFeaturesSupported(vibrator)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** @hide */
+ @Override
public boolean isHapticFeedbackCandidate() {
long totalDuration = getDuration();
if (totalDuration > MAX_HAPTIC_FEEDBACK_DURATION) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 7edcdd75..4e852e3 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -222,6 +222,28 @@
}
/**
+ * Checks whether or not the vibrator supports all components of a given {@link VibrationEffect}
+ * (i.e. the vibrator can play the given effect as intended).
+ *
+ * <p>If this method returns {@code true}, then the VibrationEffect should play as expected.
+ * If {@code false}, playing the VibrationEffect might still make a vibration, but the vibration
+ * may be significantly degraded from the intention.
+ *
+ * <p>This method aggregates the results of feature check methods such as
+ * {@link #hasAmplitudeControl}, {@link #areAllPrimitivesSupported(int...)}, etc, depending
+ * on the features that are actually used by the VibrationEffect.
+ *
+ * @param effect the {@link VibrationEffect} to check if it is supported
+ * @return {@code true} if the vibrator can play the given {@code effect} as intended,
+ * {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean areVibrationFeaturesSupported(@NonNull VibrationEffect effect) {
+ return effect.areVibrationFeaturesSupported(this);
+ }
+
+ /**
* Check whether the vibrator can be controlled by an external service with the
* {@link IExternalVibratorService}.
*
diff --git a/core/java/android/os/vibrator/PrebakedSegment.java b/core/java/android/os/vibrator/PrebakedSegment.java
index 30f5a5c..cc76ffa 100644
--- a/core/java/android/os/vibrator/PrebakedSegment.java
+++ b/core/java/android/os/vibrator/PrebakedSegment.java
@@ -22,6 +22,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import java.util.Objects;
@@ -69,6 +70,31 @@
/** @hide */
@Override
+ public boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator) {
+ if (vibrator.areAllEffectsSupported(mEffectId) == Vibrator.VIBRATION_EFFECT_SUPPORT_YES) {
+ return true;
+ }
+ if (!mFallback) {
+ // If the Vibrator's support is not `VIBRATION_EFFECT_SUPPORT_YES`, and this effect does
+ // not support fallbacks, the effect is considered not supported by the vibrator.
+ return false;
+ }
+ // The vibrator does not have hardware support for the effect, but the effect has fallback
+ // support. Check if a fallback will be available for the effect ID.
+ switch (mEffectId) {
+ case VibrationEffect.EFFECT_CLICK:
+ case VibrationEffect.EFFECT_DOUBLE_CLICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
+ case VibrationEffect.EFFECT_TICK:
+ // Any of these effects are always supported via some form of fallback.
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** @hide */
+ @Override
public boolean isHapticFeedbackCandidate() {
switch (mEffectId) {
case VibrationEffect.EFFECT_CLICK:
diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java
index 2d287e9..cde0ff3 100644
--- a/core/java/android/os/vibrator/PrimitiveSegment.java
+++ b/core/java/android/os/vibrator/PrimitiveSegment.java
@@ -22,6 +22,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import com.android.internal.util.Preconditions;
@@ -69,6 +70,12 @@
/** @hide */
@Override
+ public boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator) {
+ return vibrator.areAllPrimitivesSupported(mPrimitiveId);
+ }
+
+ /** @hide */
+ @Override
public boolean isHapticFeedbackCandidate() {
return true;
}
diff --git a/core/java/android/os/vibrator/RampSegment.java b/core/java/android/os/vibrator/RampSegment.java
index d7d8c49..034962a 100644
--- a/core/java/android/os/vibrator/RampSegment.java
+++ b/core/java/android/os/vibrator/RampSegment.java
@@ -20,6 +20,7 @@
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import com.android.internal.util.Preconditions;
@@ -95,6 +96,29 @@
/** @hide */
@Override
+ public boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator) {
+ boolean areFeaturesSupported = true;
+ // If the start/end frequencies are not the same, require frequency control since we need to
+ // ramp up/down the frequency.
+ if ((mStartFrequencyHz != mEndFrequencyHz)
+ // If there is no frequency ramping, make sure that the one frequency used does not
+ // require frequency control.
+ || frequencyRequiresFrequencyControl(mStartFrequencyHz)) {
+ areFeaturesSupported &= vibrator.hasFrequencyControl();
+ }
+ // If the start/end amplitudes are not the same, require amplitude control since we need to
+ // ramp up/down the amplitude.
+ if ((mStartAmplitude != mEndAmplitude)
+ // If there is no amplitude ramping, make sure that the amplitude used does not
+ // require amplitude control.
+ || amplitudeRequiresAmplitudeControl(mStartAmplitude)) {
+ areFeaturesSupported &= vibrator.hasAmplitudeControl();
+ }
+ return areFeaturesSupported;
+ }
+
+ /** @hide */
+ @Override
public boolean isHapticFeedbackCandidate() {
return true;
}
diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java
index 5a0bbf7..115a66c 100644
--- a/core/java/android/os/vibrator/StepSegment.java
+++ b/core/java/android/os/vibrator/StepSegment.java
@@ -21,6 +21,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import com.android.internal.util.Preconditions;
@@ -81,6 +82,19 @@
/** @hide */
@Override
+ public boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator) {
+ boolean areFeaturesSupported = true;
+ if (frequencyRequiresFrequencyControl(mFrequencyHz)) {
+ areFeaturesSupported &= vibrator.hasFrequencyControl();
+ }
+ if (amplitudeRequiresAmplitudeControl(mAmplitude)) {
+ areFeaturesSupported &= vibrator.hasAmplitudeControl();
+ }
+ return areFeaturesSupported;
+ }
+
+ /** @hide */
+ @Override
public boolean isHapticFeedbackCandidate() {
return true;
}
diff --git a/core/java/android/os/vibrator/VibrationEffectSegment.java b/core/java/android/os/vibrator/VibrationEffectSegment.java
index be10553..75a055f 100644
--- a/core/java/android/os/vibrator/VibrationEffectSegment.java
+++ b/core/java/android/os/vibrator/VibrationEffectSegment.java
@@ -21,6 +21,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.VibrationEffect;
+import android.os.Vibrator;
/**
* Representation of a single segment of a {@link VibrationEffect}.
@@ -57,6 +58,15 @@
*/
public abstract long getDuration();
+ /**
+ * Checks if a given {@link Vibrator} can play this segment as intended. See
+ * {@link Vibrator#areVibrationFeaturesSupported(VibrationEffect)} for more information about
+ * what counts as supported by a vibrator, and what counts as not.
+ *
+ * @hide
+ */
+ public abstract boolean areVibrationFeaturesSupported(@NonNull Vibrator vibrator);
+
/**
* Returns true if this segment could be a haptic feedback effect candidate.
*
@@ -149,6 +159,28 @@
}
}
+ /**
+ * Helper method to check if an amplitude requires a vibrator to have amplitude control to play.
+ *
+ * @hide
+ */
+ protected static boolean amplitudeRequiresAmplitudeControl(float amplitude) {
+ return (amplitude != 0)
+ && (amplitude != 1)
+ && (amplitude != VibrationEffect.DEFAULT_AMPLITUDE);
+ }
+
+ /**
+ * Helper method to check if a frequency requires a vibrator to have frequency control to play.
+ *
+ * @hide
+ */
+ protected static boolean frequencyRequiresFrequencyControl(float frequency) {
+ // Anything other than the default frequency value (represented with "0") requires frequency
+ // control.
+ return frequency != 0;
+ }
+
@NonNull
public static final Creator<VibrationEffectSegment> CREATOR =
new Creator<VibrationEffectSegment>() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b510fad..5b05f21 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1060,8 +1060,13 @@
* In some cases, a matching Activity may not exist, so ensure you
* safeguard against this.
* <p>
- * Input: Nothing.
- * <p>
+ * Input: The optional {@code #EXTRA_EXPLICIT_LOCALES} with language tags that contains locales
+ * to limit available locales. This is only supported when device is under demo mode.
+ * If intent does not contain this extra, it will show system supported locale list.
+ * <br/>
+ * If {@code #EXTRA_EXPLICIT_LOCALES} contain a unsupported locale, it will still show this
+ * locale on list, but may not be supported by the devcie.
+ *
* Output: Nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -1069,6 +1074,18 @@
"android.settings.LOCALE_SETTINGS";
/**
+ * Activity Extra: Show explicit locales in launched locale picker activity.
+ *
+ * This can be passed as an extra field in an Activity Intent with one or more language tags
+ * as a {@link LocaleList}. This must be passed as an extra field to the
+ * {@link #ACTION_LOCALE_SETTINGS}.
+ *
+ * @hide
+ */
+ public static final String EXTRA_EXPLICIT_LOCALES =
+ "android.provider.extra.EXPLICIT_LOCALES";
+
+ /**
* Activity Action: Show settings to allow configuration of per application locale.
* <p>
* Input: The Intent's data URI can specify the application package name to directly invoke the
@@ -1694,6 +1711,7 @@
* Input: Nothing.
* <p>
* Output: Nothing
+ * @see android.nfc.NfcAdapter#isNdefPushEnabled()
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NFCSHARING_SETTINGS =
@@ -6142,7 +6160,6 @@
MOVED_TO_GLOBAL.add(Settings.Global.ADB_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.ASSISTED_GPS_ENABLED);
MOVED_TO_GLOBAL.add(Settings.Global.BLUETOOTH_ON);
- MOVED_TO_GLOBAL.add(Settings.Global.BUGREPORT_IN_POWER_MENU);
MOVED_TO_GLOBAL.add(Settings.Global.CDMA_CELL_BROADCAST_SMS);
MOVED_TO_GLOBAL.add(Settings.Global.CDMA_ROAMING_MODE);
MOVED_TO_GLOBAL.add(Settings.Global.CDMA_SUBSCRIPTION_MODE);
@@ -6763,14 +6780,26 @@
/**
* When the user has enable the option to have a "bug report" command
* in the power menu.
- * @deprecated Use {@link android.provider.Settings.Global#BUGREPORT_IN_POWER_MENU} instead
* @hide
*/
- @Deprecated
@Readable
public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
/**
+ * The package name for the custom bugreport handler app. This app must be bugreport
+ * allow-listed. This is currently used only by Power Menu short press.
+ * @hide
+ */
+ public static final String CUSTOM_BUGREPORT_HANDLER_APP = "custom_bugreport_handler_app";
+
+ /**
+ * The user id for the custom bugreport handler app. This is currently used only by Power
+ * Menu short press.
+ * @hide
+ */
+ public static final String CUSTOM_BUGREPORT_HANDLER_USER = "custom_bugreport_handler_user";
+
+ /**
* @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead
*/
@Deprecated
@@ -10013,9 +10042,11 @@
/**
* Whether or not a SFPS device is enabling the performant auth setting.
+ * The "_V2" suffix was added to re-introduce the default behavior for
+ * users. See b/265264294 fore more details.
* @hide
*/
- public static final String SFPS_PERFORMANT_AUTH_ENABLED = "sfps_performant_auth_enabled";
+ public static final String SFPS_PERFORMANT_AUTH_ENABLED = "sfps_performant_auth_enabled_v2";
/**
* Whether or not debugging is enabled.
@@ -11719,26 +11750,32 @@
/**
* When the user has enable the option to have a "bug report" command
* in the power menu.
+ * @deprecated Use {@link android.provider.Settings.Secure#BUGREPORT_IN_POWER_MENU} instead
* @hide
*/
+ @Deprecated
@Readable
public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
/**
* The package name for the custom bugreport handler app. This app must be whitelisted.
* This is currently used only by Power Menu short press.
- *
+ * @deprecated Use {@link android.provider.Settings.Secure#CUSTOM_BUGREPORT_HANDLER_APP}
+ * instead
* @hide
*/
+ @Deprecated
@Readable
public static final String CUSTOM_BUGREPORT_HANDLER_APP = "custom_bugreport_handler_app";
/**
* The user id for the custom bugreport handler app. This is currently used only by Power
* Menu short press.
- *
+ * @deprecated Use {@link android.provider.Settings.Secure#CUSTOM_BUGREPORT_HANDLER_USER}
+ * instead
* @hide
*/
+ @Deprecated
@Readable
public static final String CUSTOM_BUGREPORT_HANDLER_USER = "custom_bugreport_handler_user";
@@ -15729,8 +15766,13 @@
public static final String NETWORK_SCORING_PROVISIONED = "network_scoring_provisioned";
/**
- * Indicates whether the user wants to be prompted for password to decrypt the device on
- * boot. This only matters if the storage is encrypted.
+ * On devices that use full-disk encryption, indicates whether the primary user's lockscreen
+ * credential is required to decrypt the device on boot.
+ * <p>
+ * This setting does not do anything on devices that use file-based encryption. With
+ * file-based encryption, the device boots without a credential being needed, but the
+ * lockscreen credential is required to unlock credential-encrypted storage. All devices
+ * that launched with Android 10 or higher use file-based encryption.
* <p>
* Type: int (0 for false, 1 for true)
*
@@ -16357,6 +16399,9 @@
MOVED_TO_SECURE.add(Global.CHARGING_SOUNDS_ENABLED);
MOVED_TO_SECURE.add(Global.CHARGING_VIBRATION_ENABLED);
MOVED_TO_SECURE.add(Global.NOTIFICATION_BUBBLES);
+ MOVED_TO_SECURE.add(Global.BUGREPORT_IN_POWER_MENU);
+ MOVED_TO_SECURE.add(Global.CUSTOM_BUGREPORT_HANDLER_APP);
+ MOVED_TO_SECURE.add(Global.CUSTOM_BUGREPORT_HANDLER_USER);
}
// Certain settings have been moved from global to the per-user system namespace
@@ -17957,6 +18002,28 @@
public static final String OEM_SETUP_VERSION = "oem_setup_version";
/**
+ * The key to indicate to Setup Wizard if OEM setup is completed in Wear Services.
+ * @hide
+ */
+ public static final String OEM_SETUP_COMPLETED_STATUS = "oem_setup_completed_status";
+
+ /**
+ * Constant provided to Setup Wizard to inform about failure of OEM setup in Wear
+ * Services. The value should be provided with setting name {@link
+ * #OEM_SETUP_COMPLETED_STATUS}.
+ * @hide
+ */
+ public static final int OEM_SETUP_COMPLETED_FAILURE = 0;
+
+ /**
+ * Constant provided to Setup Wizard to inform about successful completion of OEM setup
+ * in Wear Services. The value should be provided with setting name {@link
+ * #OEM_SETUP_COMPLETED_STATUS}.
+ * @hide
+ */
+ public static final int OEM_SETUP_COMPLETED_SUCCESS = 1;
+
+ /**
* Controls the gestures feature.
* @hide
*/
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 6e8198b..bf5b970 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -51,6 +51,11 @@
}
@Override
+ public void endDream() {
+ onEndDream();
+ }
+
+ @Override
public void wakeUp() {
onWakeUp(() -> {
try {
@@ -83,13 +88,22 @@
/**
* This method is overridden by implementations to handle when the dream has been requested
- * to wakeup. This allows any overlay animations to run.
+ * to wakeup. This allows any overlay animations to run. By default, the method will invoke
+ * the callback immediately.
*
* @param onCompleteCallback The callback to trigger to notify the dream service that the
* overlay has completed waking up.
* @hide
*/
public void onWakeUp(@NonNull Runnable onCompleteCallback) {
+ onCompleteCallback.run();
+ }
+
+ /**
+ * This method is overridden by implementations to handle when the dream has ended. There may
+ * be earlier signals leading up to this step, such as @{@link #onWakeUp(Runnable)}.
+ */
+ public void onEndDream() {
}
/**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 8b9852a..d378886 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -297,14 +297,20 @@
}
public void addConsumer(Consumer<IDreamOverlay> consumer) {
- mConsumers.add(consumer);
- if (mOverlay != null) {
- consumer.accept(mOverlay);
- }
+ execute(() -> {
+ mConsumers.add(consumer);
+ if (mOverlay != null) {
+ consumer.accept(mOverlay);
+ }
+ });
}
public void removeConsumer(Consumer<IDreamOverlay> consumer) {
- mConsumers.remove(consumer);
+ execute(() -> mConsumers.remove(consumer));
+ }
+
+ public void clearConsumers() {
+ execute(() -> mConsumers.clear());
}
}
@@ -1383,6 +1389,17 @@
@Override
public void onViewDetachedFromWindow(View v) {
+ if (mOverlayConnection != null) {
+ mOverlayConnection.addConsumer(overlay -> {
+ try {
+ overlay.endDream();
+ } catch (RemoteException e) {
+ Log.e(mTag, "could not inform overlay of dream end:" + e);
+ }
+ });
+ mOverlayConnection.clearConsumers();
+ }
+
if (mActivity == null || !mActivity.isChangingConfigurations()) {
// Only stop the dream if the view is not detached by relaunching
// activity for configuration changes. It is important to also clear
@@ -1391,9 +1408,6 @@
mActivity = null;
finish();
}
- if (mOverlayConnection != null && mDreamStartOverlayConsumer != null) {
- mOverlayConnection.removeConsumer(mDreamStartOverlayConsumer);
- }
}
});
}
diff --git a/core/java/android/service/dreams/IDreamOverlay.aidl b/core/java/android/service/dreams/IDreamOverlay.aidl
index 7aeceb2c..0e4bd3b 100644
--- a/core/java/android/service/dreams/IDreamOverlay.aidl
+++ b/core/java/android/service/dreams/IDreamOverlay.aidl
@@ -41,4 +41,7 @@
/** Called when the dream is waking, to do any exit animations */
void wakeUp();
+
+ /** Called when the dream has ended. */
+ void endDream();
}
diff --git a/core/java/android/service/quickaccesswallet/WalletCard.java b/core/java/android/service/quickaccesswallet/WalletCard.java
index b09d2e9..950f9b5 100644
--- a/core/java/android/service/quickaccesswallet/WalletCard.java
+++ b/core/java/android/service/quickaccesswallet/WalletCard.java
@@ -16,6 +16,7 @@
package android.service.quickaccesswallet;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
@@ -24,28 +25,70 @@
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
/**
* A {@link WalletCard} can represent anything that a user might carry in their wallet -- a credit
* card, library card, transit pass, etc. Cards are identified by a String identifier and contain a
- * card image, card image content description, and a {@link PendingIntent} to be used if the user
- * clicks on the card. Cards may be displayed with an icon and label, though these are optional.
+ * card type, card image, card image content description, and a {@link PendingIntent} to be used if
+ * the user clicks on the card. Cards may be displayed with an icon and label, though these are
+ * optional. Valuable cards will also have a second image that will be displayed when the card is
+ * tapped.
*/
+
public final class WalletCard implements Parcelable {
+ /**
+ * Unknown cards refer to cards whose types are unspecified.
+ */
+ public static final int CARD_TYPE_UNKNOWN = 0;
+
+ /**
+ * Payment cards refer to credit cards, debit cards or any other cards in the wallet used to
+ * make cash-equivalent payments.
+ */
+ public static final int CARD_TYPE_PAYMENT = 1;
+
+ /**
+ * Valuable cards refer to any cards that are not used for cash-equivalent payment.
+ * This includes event tickets, flights, offers, loyalty cards, gift cards and transit tickets.
+ */
+ public static final int CARD_TYPE_VALUABLE = 2;
+
private final String mCardId;
+ private final int mCardType;
private final Icon mCardImage;
private final CharSequence mContentDescription;
private final PendingIntent mPendingIntent;
private final Icon mCardIcon;
private final CharSequence mCardLabel;
+ private final Icon mValuableCardSecondaryImage;
private WalletCard(Builder builder) {
this.mCardId = builder.mCardId;
+ this.mCardType = builder.mCardType;
this.mCardImage = builder.mCardImage;
this.mContentDescription = builder.mContentDescription;
this.mPendingIntent = builder.mPendingIntent;
this.mCardIcon = builder.mCardIcon;
this.mCardLabel = builder.mCardLabel;
+ this.mValuableCardSecondaryImage = builder.mValuableCardSecondaryImage;
+ }
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"CARD_TYPE_"}, value = {
+ CARD_TYPE_UNKNOWN,
+ CARD_TYPE_PAYMENT,
+ CARD_TYPE_VALUABLE
+ })
+ public @interface CardType {
}
@Override
@@ -56,29 +99,44 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mCardId);
+ dest.writeInt(mCardType);
mCardImage.writeToParcel(dest, flags);
TextUtils.writeToParcel(mContentDescription, dest, flags);
PendingIntent.writePendingIntentOrNullToParcel(mPendingIntent, dest);
- if (mCardIcon == null) {
+ writeIconIfNonNull(mCardIcon, dest, flags);
+ TextUtils.writeToParcel(mCardLabel, dest, flags);
+ writeIconIfNonNull(mValuableCardSecondaryImage, dest, flags);
+
+ }
+
+ /** Utility function called by writeToParcel
+ */
+ private void writeIconIfNonNull(Icon icon, Parcel dest, int flags) {
+ if (icon == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
- mCardIcon.writeToParcel(dest, flags);
+ icon.writeToParcel(dest, flags);
}
- TextUtils.writeToParcel(mCardLabel, dest, flags);
}
private static WalletCard readFromParcel(Parcel source) {
String cardId = source.readString();
+ int cardType = source.readInt();
Icon cardImage = Icon.CREATOR.createFromParcel(source);
CharSequence contentDesc = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
PendingIntent pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(source);
Icon cardIcon = source.readByte() == 0 ? null : Icon.CREATOR.createFromParcel(source);
CharSequence cardLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- return new Builder(cardId, cardImage, contentDesc, pendingIntent)
+ Icon valuableCardSecondaryImage = source.readByte() == 0 ? null :
+ Icon.CREATOR.createFromParcel(source);
+ Builder builder = new Builder(cardId, cardType, cardImage, contentDesc, pendingIntent)
.setCardIcon(cardIcon)
- .setCardLabel(cardLabel)
- .build();
+ .setCardLabel(cardLabel);
+
+ return cardType == CARD_TYPE_VALUABLE
+ ? builder.setValuableCardSecondaryImage(valuableCardSecondaryImage).build() :
+ builder.build();
}
@NonNull
@@ -104,6 +162,15 @@
}
/**
+ * Returns the card type.
+ */
+ @NonNull
+ @CardType
+ public int getCardType() {
+ return mCardType;
+ }
+
+ /**
* The visual representation of the card. If the card image Icon is a bitmap, it should have a
* width of {@link GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
* GetWalletCardsRequest#getCardHeightPx()}.
@@ -158,23 +225,36 @@
}
/**
- * Builder for {@link WalletCard} objects. You must to provide cardId, cardImage,
+ * Visual representation of the card when it is tapped. Includes a barcode to scan the card in
+ * addition to the information in the primary image.
+ */
+ @Nullable
+ public Icon getValuableCardSecondaryImage() {
+ return mValuableCardSecondaryImage;
+ }
+
+ /**
+ * Builder for {@link WalletCard} objects. You must provide cardId, cardImage,
* contentDescription, and pendingIntent. If the card is opaque and should be shown with
* elevation, set hasShadow to true. cardIcon and cardLabel are optional.
*/
public static final class Builder {
private String mCardId;
+ private int mCardType;
private Icon mCardImage;
private CharSequence mContentDescription;
private PendingIntent mPendingIntent;
private Icon mCardIcon;
private CharSequence mCardLabel;
+ private Icon mValuableCardSecondaryImage;
/**
* @param cardId The card id must be non-null and unique within the list of
* cards returned. <b>Note:
* </b> this card ID should <b>not</b> contain PII (Personally
* Identifiable Information, such as username or email address).
+ * @param cardType Integer representing the card type. The card type must be
+ * non-null. If not provided, it defaults to unknown.
* @param cardImage The visual representation of the card. If the card image Icon
* is a bitmap, it should have a width of {@link
* GetWalletCardsRequest#getCardWidthPx()} and a height of {@link
@@ -193,15 +273,31 @@
* request device unlock before sending the pending intent. It is
* recommended that the pending intent be immutable (use {@link
* PendingIntent#FLAG_IMMUTABLE}).
+ *
+ */
+ public Builder(@NonNull String cardId,
+ @NonNull @CardType int cardType,
+ @NonNull Icon cardImage,
+ @NonNull CharSequence contentDescription,
+ @NonNull PendingIntent pendingIntent
+ ) {
+ mCardId = cardId;
+ mCardType = cardType;
+ mCardImage = cardImage;
+ mContentDescription = contentDescription;
+ mPendingIntent = pendingIntent;
+ }
+
+ /**
+ * Called when a card type is not provided. Calls {@link
+ * Builder#Builder(String, int, Icon, CharSequence, PendingIntent)} with default card type
*/
public Builder(@NonNull String cardId,
@NonNull Icon cardImage,
@NonNull CharSequence contentDescription,
@NonNull PendingIntent pendingIntent) {
- mCardId = cardId;
- mCardImage = cardImage;
- mContentDescription = contentDescription;
- mPendingIntent = pendingIntent;
+ this(cardId, WalletCard.CARD_TYPE_UNKNOWN, cardImage, contentDescription,
+ pendingIntent);
}
/**
@@ -236,6 +332,18 @@
}
/**
+ * Visual representation of the card when it is tapped. Includes a barcode to scan the card
+ * in addition to the information in the primary image.
+ */
+ @NonNull
+ public Builder setValuableCardSecondaryImage(@Nullable Icon valuableCardSecondaryImage) {
+ Preconditions.checkState(mCardType == CARD_TYPE_VALUABLE,
+ "This field can only be set on valuable cards");
+ mValuableCardSecondaryImage = valuableCardSecondaryImage;
+ return this;
+ }
+
+ /**
* Builds a new {@link WalletCard} instance.
*
* @return A built response.
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index df739e3..ca4716b 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -95,20 +95,6 @@
public static final String SERVICE_META_DATA = "android.voice_interaction";
/**
- * Bundle key used to specify the id when the system prepares to show session. It increases for
- * each request.
- * <p>
- * Type: int
- * </p>
- * @see #showSession(Bundle, int)
- * @see #onPrepareToShowSession(Bundle, int)
- * @see #onShowSessionFailed(Bundle)
- * @see VoiceInteractionSession#onShow(Bundle, int)
- * @see VoiceInteractionSession#show(Bundle, int)
- */
- public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
-
- /**
* For apps targeting Build.VERSION_CODES.TRAMISU and above, implementors of this
* service can create multiple AlwaysOnHotwordDetector instances in parallel. They will
* also e ale to create a single SoftwareHotwordDetector in parallel with any other
@@ -219,7 +205,7 @@
* bind the session service.
*
* @param args The arguments that were supplied to {@link #showSession(Bundle, int)}.
- * It always includes {@link #KEY_SHOW_SESSION_ID}.
+ * It always includes {@link VoiceInteractionSession#KEY_SHOW_SESSION_ID}.
* @param flags The show flags originally provided to {@link #showSession(Bundle, int)}.
* @see #showSession(Bundle, int)
* @see #onShowSessionFailed(Bundle)
@@ -233,7 +219,7 @@
* Called when the show session failed. E.g. When the system bound the session service failed.
*
* @param args Additional info about the show session attempt that failed. For now, includes
- * {@link #KEY_SHOW_SESSION_ID}.
+ * {@link VoiceInteractionSession#KEY_SHOW_SESSION_ID}.
* @see #showSession(Bundle, int)
* @see #onPrepareToShowSession(Bundle, int)
* @see VoiceInteractionSession#onShow(Bundle, int)
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index d55fede..0d51395 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -169,6 +169,20 @@
@Retention(RetentionPolicy.SOURCE)
public @interface VoiceInteractionActivityEventType{}
+ /**
+ * Bundle key used to specify the id when the system prepares to show session. It increases for
+ * each request.
+ * <p>
+ * Type: int
+ * </p>
+ * @see VoiceInteractionService#showSession(Bundle, int)
+ * @see VoiceInteractionService#onPrepareToShowSession(Bundle, int)
+ * @see VoiceInteractionService#onShowSessionFailed(Bundle)
+ * @see #onShow(Bundle, int)
+ * @see #show(Bundle, int)
+ */
+ public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
+
final Context mContext;
final HandlerCaller mHandlerCaller;
@@ -1763,7 +1777,7 @@
* @param args The arguments that were supplied to
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
* Some example keys include : "invocation_type", "invocation_phone_state",
- * {@link VoiceInteractionService#KEY_SHOW_SESSION_ID}, "invocation_time_ms",
+ * {@link #KEY_SHOW_SESSION_ID}, "invocation_time_ms",
* Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing
* in milliseconds of the KeyEvent that triggered Assistant and
* Intent.EXTRA_ASSIST_INPUT_DEVICE_ID (android.intent.extra.ASSIST_INPUT_DEVICE_ID)
diff --git a/core/java/android/text/method/InsertModeTransformationMethod.java b/core/java/android/text/method/InsertModeTransformationMethod.java
new file mode 100644
index 0000000..fbdaa3d
--- /dev/null
+++ b/core/java/android/text/method/InsertModeTransformationMethod.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.style.ReplacementSpan;
+import android.util.DisplayMetrics;
+import android.util.MathUtils;
+import android.util.TypedValue;
+import android.view.View;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+
+/**
+ * The transformation method used by handwriting insert mode.
+ * This transformation will insert a placeholder string to the original text at the given
+ * offset. And it also provides a highlight range for the newly inserted text and the placeholder
+ * text.
+ *
+ * For example,
+ * original text: "Hello world"
+ * insert mode is started at index: 5,
+ * placeholder text: "\n\n"
+ * The transformed text will be: "Hello\n\n world", and the highlight range will be [5, 7)
+ * including the inserted placeholder text.
+ *
+ * If " abc" is inserted to the original text at index 5,
+ * the new original text: "Hello abc world"
+ * the new transformed text: "hello abc\n\n world", and the highlight range will be [5, 11).
+ * @hide
+ */
+public class InsertModeTransformationMethod implements TransformationMethod, TextWatcher {
+ /** The start offset of the highlight range in the original text, inclusive. */
+ private int mStart;
+ /**
+ * The end offset of the highlight range in the original text, exclusive. The placeholder text
+ * is also inserted at this index.
+ */
+ private int mEnd;
+ /** The transformation method that's already set on the {@link android.widget.TextView}. */
+ private final TransformationMethod mOldTransformationMethod;
+ /** Whether the {@link android.widget.TextView} is single-lined. */
+ private final boolean mSingleLine;
+
+ /**
+ * @param offset the original offset to start the insert mode. It must be in the range from 0
+ * to the length of the transformed text.
+ * @param singleLine whether the text is single line.
+ * @param oldTransformationMethod the old transformation method at the
+ * {@link android.widget.TextView}. If it's not null, this {@link TransformationMethod} will
+ * first call {@link TransformationMethod#getTransformation(CharSequence, View)} on the old one,
+ * and then do the transformation for the insert mode.
+ *
+ */
+ public InsertModeTransformationMethod(@IntRange(from = 0) int offset, boolean singleLine,
+ @NonNull TransformationMethod oldTransformationMethod) {
+ mStart = offset;
+ mEnd = offset;
+ mSingleLine = singleLine;
+ mOldTransformationMethod = oldTransformationMethod;
+ }
+
+ public TransformationMethod getOldTransformationMethod() {
+ return mOldTransformationMethod;
+ }
+
+ private CharSequence getPlaceholderText(View view) {
+ if (!mSingleLine) {
+ return "\n\n";
+ }
+ final SpannableString singleLinePlaceholder = new SpannableString("\uFFFD");
+ final DisplayMetrics displayMetrics = view.getResources().getDisplayMetrics();
+ final int widthPx = (int) Math.ceil(
+ TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 108, displayMetrics));
+
+ singleLinePlaceholder.setSpan(new SingleLinePlaceholderSpan(widthPx), 0, 1,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return singleLinePlaceholder;
+ }
+
+ @Override
+ public CharSequence getTransformation(CharSequence source, View view) {
+ final CharSequence charSequence;
+ if (mOldTransformationMethod != null) {
+ charSequence = mOldTransformationMethod.getTransformation(source, view);
+ if (source instanceof Spannable) {
+ final Spannable spannable = (Spannable) source;
+ spannable.setSpan(mOldTransformationMethod, 0, spannable.length(),
+ Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
+ } else {
+ charSequence = source;
+ }
+
+ final CharSequence placeholderText = getPlaceholderText(view);
+ return new TransformedText(charSequence, placeholderText);
+ }
+
+ @Override
+ public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction,
+ Rect previouslyFocusedRect) {
+ if (mOldTransformationMethod != null) {
+ mOldTransformationMethod.onFocusChanged(view, sourceText, focused, direction,
+ previouslyFocusedRect);
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // The text change is after the offset where placeholder is inserted, return.
+ if (start > mEnd) return;
+ final int diff = count - before;
+
+ // Note: If start == mStart and before == 0, the change is also considered after the
+ // highlight start. It won't modify the mStart in this case.
+ if (start < mStart) {
+ if (start + before <= mStart) {
+ // The text change is before the highlight start, move the highlight start.
+ mStart += diff;
+ } else {
+ // The text change covers the highlight start. Extend the highlight start to the
+ // change start. This should be a rare case.
+ mStart = start;
+ }
+ }
+
+ if (start + before <= mEnd) {
+ // The text change is before the highlight end, move the highlight end.
+ mEnd += diff;
+ } else if (start < mEnd) {
+ // The text change covers the highlight end. Extend the highlight end to the
+ // change end. This should be a rare case.
+ mEnd = start + count;
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) { }
+
+ /**
+ * The transformed text returned by the {@link InsertModeTransformationMethod}.
+ */
+ public class TransformedText implements OffsetMapping, Spanned {
+ private final CharSequence mOriginal;
+ private final CharSequence mPlaceholder;
+ private final Spanned mSpannedOriginal;
+ private final Spanned mSpannedPlaceholder;
+
+ TransformedText(CharSequence original, CharSequence placeholder) {
+ mOriginal = original;
+ if (original instanceof Spanned) {
+ mSpannedOriginal = (Spanned) original;
+ } else {
+ mSpannedOriginal = null;
+ }
+ mPlaceholder = placeholder;
+ if (placeholder instanceof Spanned) {
+ mSpannedPlaceholder = (Spanned) placeholder;
+ } else {
+ mSpannedPlaceholder = null;
+ }
+ }
+
+ @Override
+ public int originalToTransformed(int offset, int strategy) {
+ if (offset < 0) return offset;
+ Preconditions.checkArgumentInRange(offset, 0, mOriginal.length(), "offset");
+ if (offset == mEnd && strategy == OffsetMapping.MAP_STRATEGY_CURSOR) {
+ // The offset equals to mEnd. For a cursor position it's considered before the
+ // inserted placeholder text.
+ return offset;
+ }
+ if (offset < mEnd) {
+ return offset;
+ }
+ return offset + mPlaceholder.length();
+ }
+
+ @Override
+ public int transformedToOriginal(int offset, int strategy) {
+ if (offset < 0) return offset;
+ Preconditions.checkArgumentInRange(offset, 0, length(), "offset");
+
+ // The placeholder text is inserted at mEnd. Because the offset is smaller than
+ // mEnd, we can directly return it.
+ if (offset < mEnd) return offset;
+ if (offset < mEnd + mPlaceholder.length()) {
+ return mEnd;
+ }
+ return offset - mPlaceholder.length();
+ }
+
+ @Override
+ public void originalToTransformed(TextUpdate textUpdate) {
+ if (textUpdate.where > mEnd) {
+ textUpdate.where += mPlaceholder.length();
+ } else if (textUpdate.where + textUpdate.before > mEnd) {
+ // The update also covers the placeholder string.
+ textUpdate.before += mPlaceholder.length();
+ textUpdate.after += mPlaceholder.length();
+ }
+ }
+
+ @Override
+ public int length() {
+ return mOriginal.length() + mPlaceholder.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ Preconditions.checkArgumentInRange(index, 0, length() - 1, "index");
+ if (index < mEnd) {
+ return mOriginal.charAt(index);
+ }
+ if (index < mEnd + mPlaceholder.length()) {
+ return mPlaceholder.charAt(index - mEnd);
+ }
+ return mOriginal.charAt(index - mPlaceholder.length());
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ if (end < start || start < 0 || end > length()) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (start == end) {
+ return "";
+ }
+
+ final int placeholderLength = mPlaceholder.length();
+
+ final int seg1Start = Math.min(start, mEnd);
+ final int seg1End = Math.min(end, mEnd);
+
+ final int seg2Start = MathUtils.constrain(start - mEnd, 0, placeholderLength);
+ final int seg2End = MathUtils.constrain(end - mEnd, 0, placeholderLength);
+
+ final int seg3Start = Math.max(start - placeholderLength, mEnd);
+ final int seg3End = Math.max(end - placeholderLength, mEnd);
+
+ return TextUtils.concat(
+ mOriginal.subSequence(seg1Start, seg1End),
+ mPlaceholder.subSequence(seg2Start, seg2End),
+ mOriginal.subSequence(seg3Start, seg3End));
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mOriginal.subSequence(0, mEnd))
+ + mPlaceholder
+ + mOriginal.subSequence(mEnd, mOriginal.length());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T[] getSpans(int start, int end, Class<T> type) {
+ if (end < start) {
+ return ArrayUtils.emptyArray(type);
+ }
+
+ final T[] spansOriginal;
+ if (mSpannedOriginal != null) {
+ final int originalStart =
+ transformedToOriginal(start, OffsetMapping.MAP_STRATEGY_CURSOR);
+ final int originalEnd =
+ transformedToOriginal(end, OffsetMapping.MAP_STRATEGY_CURSOR);
+ spansOriginal = mSpannedOriginal.getSpans(originalStart, originalEnd, type);
+ } else {
+ spansOriginal = null;
+ }
+
+ final T[] spansPlaceholder;
+ if (mSpannedPlaceholder != null
+ && intersect(start, end, mEnd, mEnd + mPlaceholder.length())) {
+ final int placeholderStart = Math.max(start - mEnd, 0);
+ final int placeholderEnd = Math.min(end - mEnd, mPlaceholder.length());
+ spansPlaceholder =
+ mSpannedPlaceholder.getSpans(placeholderStart, placeholderEnd, type);
+ } else {
+ spansPlaceholder = null;
+ }
+
+ // TODO: sort the spans based on their priority.
+ return ArrayUtils.concat(type, spansOriginal, spansPlaceholder);
+ }
+
+ @Override
+ public int getSpanStart(Object tag) {
+ if (mSpannedOriginal != null) {
+ final int index = mSpannedOriginal.getSpanStart(tag);
+ if (index >= 0) {
+ if (index < mEnd) {
+ return index;
+ }
+ return index + mPlaceholder.length();
+ }
+ }
+
+ // The span is not on original text, try find it on the placeholder.
+ if (mSpannedPlaceholder != null) {
+ final int index = mSpannedPlaceholder.getSpanStart(tag);
+ if (index >= 0) {
+ // Find the span on placeholder, transform it and return.
+ return index + mEnd;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getSpanEnd(Object tag) {
+ if (mSpannedOriginal != null) {
+ final int index = mSpannedOriginal.getSpanEnd(tag);
+ if (index >= 0) {
+ if (index <= mEnd) {
+ return index;
+ }
+ return index + mPlaceholder.length();
+ }
+ }
+
+ // The span is not on original text, try find it on the placeholder.
+ if (mSpannedPlaceholder != null) {
+ final int index = mSpannedPlaceholder.getSpanEnd(tag);
+ if (index >= 0) {
+ // Find the span on placeholder, transform it and return.
+ return index + mEnd;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getSpanFlags(Object tag) {
+ if (mSpannedOriginal != null) {
+ final int flags = mSpannedOriginal.getSpanFlags(tag);
+ if (flags != 0) {
+ return flags;
+ }
+ }
+ if (mSpannedPlaceholder != null) {
+ return mSpannedPlaceholder.getSpanFlags(tag);
+ }
+ return 0;
+ }
+
+ @Override
+ public int nextSpanTransition(int start, int limit, Class type) {
+ if (limit <= start) return limit;
+ final Object[] spans = getSpans(start, limit, type);
+ for (int i = 0; i < spans.length; ++i) {
+ int spanStart = getSpanStart(spans[i]);
+ int spanEnd = getSpanEnd(spans[i]);
+ if (start < spanStart && spanStart < limit) {
+ limit = spanStart;
+ }
+ if (start < spanEnd && spanEnd < limit) {
+ limit = spanEnd;
+ }
+ }
+ return limit;
+ }
+
+ /**
+ * Return the start index of the highlight range for the insert mode, inclusive.
+ */
+ public int getHighlightStart() {
+ return mStart;
+ }
+
+ /**
+ * Return the end index of the highlight range for the insert mode, exclusive.
+ */
+ public int getHighlightEnd() {
+ return mEnd + mPlaceholder.length();
+ }
+ }
+
+ /**
+ * The placeholder span used for single line
+ */
+ public static class SingleLinePlaceholderSpan extends ReplacementSpan {
+ private final int mWidth;
+ SingleLinePlaceholderSpan(int width) {
+ mWidth = width;
+ }
+ @Override
+ public int getSize(@NonNull Paint paint, CharSequence text, int start, int end,
+ @Nullable Paint.FontMetricsInt fm) {
+ return mWidth;
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x,
+ int top, int y, int bottom, @NonNull Paint paint) { }
+ }
+
+ /**
+ * Return true if the given two ranges intersects. This logic is the same one used in
+ * {@link Spanned} to determine whether a span range intersect with the query range.
+ */
+ private static boolean intersect(int s1, int e1, int s2, int e2) {
+ if (s1 > e2) return false;
+ if (e1 < s2) return false;
+ if (s1 != e1 && s2 != e2) {
+ if (s1 == e2) return false;
+ if (e1 == s2) return false;
+ }
+ return true;
+ }
+}
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index 787ffb7..dc06671 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -156,14 +156,14 @@
* AttachedSurfaceControl. This includes SurfaceView, and an example usage may
* be to ensure that SurfaceView with {@link android.view.SurfaceView#setZOrderOnTop}
* are cropped to a region not including the app bar.
- *
+ * <p>
* This cropped is expressed in terms of insets in window-space. Negative insets
* are considered invalid and will produce an exception. Insets of zero will produce
* the same result as if this function had never been called.
*
* @param insets The insets in each direction by which to bound the children
* expressed in window-space.
- * @hide
+ * @throws IllegalArgumentException If negative insets are provided.
*/
default void setChildBoundingInsets(@NonNull Rect insets) {
}
diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java
index 2e4073e..8d221ab 100644
--- a/core/java/android/view/HandwritingInitiator.java
+++ b/core/java/android/view/HandwritingInitiator.java
@@ -19,6 +19,7 @@
import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
import android.graphics.Rect;
import android.view.inputmethod.InputMethodManager;
@@ -77,6 +78,15 @@
private int mConnectionCount = 0;
private final InputMethodManager mImm;
+ /**
+ * The handwrite-able View that is currently the target of a hovering stylus pointer. This is
+ * used to help determine whether the handwriting PointerIcon should be shown in
+ * {@link #onResolvePointerIcon(Context, MotionEvent)} so that we can reduce the number of calls
+ * to {@link #findBestCandidateView(float, float)}.
+ */
+ @Nullable
+ private View mCachedHoverTarget = null;
+
@VisibleForTesting
public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration,
@NonNull InputMethodManager inputMethodManager) {
@@ -308,6 +318,48 @@
}
/**
+ * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
+ * This gives HandwritingInitiator a chance to show the stylus handwriting icon over a
+ * handwrite-able area.
+ */
+ public PointerIcon onResolvePointerIcon(Context context, MotionEvent event) {
+ if (shouldShowHandwritingPointerIcon(event)) {
+ return PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING);
+ }
+ return null;
+ }
+
+ private boolean shouldShowHandwritingPointerIcon(MotionEvent event) {
+ if (!event.isStylusPointer() || !event.isHoverEvent()) {
+ return false;
+ }
+
+ if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
+ || event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
+ final float hoverX = event.getX(event.getActionIndex());
+ final float hoverY = event.getY(event.getActionIndex());
+
+ if (mCachedHoverTarget != null) {
+ final Rect handwritingArea = getViewHandwritingArea(mCachedHoverTarget);
+ if (isInHandwritingArea(handwritingArea, hoverX, hoverY, mCachedHoverTarget)
+ && shouldTriggerStylusHandwritingForView(mCachedHoverTarget)) {
+ return true;
+ }
+ }
+
+ final View candidateView = findBestCandidateView(hoverX, hoverY);
+
+ if (candidateView != null) {
+ mCachedHoverTarget = candidateView;
+ return true;
+ }
+ }
+
+ mCachedHoverTarget = null;
+ return false;
+ }
+
+ /**
* Given the location of the stylus event, return the best candidate view to initialize
* handwriting mode.
*
@@ -437,7 +489,7 @@
* Return true if the (x, y) is inside by the given {@link Rect} with the View's
* handwriting bounds with offsets applied.
*/
- private boolean isInHandwritingArea(@Nullable Rect handwritingArea,
+ private static boolean isInHandwritingArea(@Nullable Rect handwritingArea,
float x, float y, View view) {
if (handwritingArea == null) return false;
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index fc47e69..5810642 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -153,6 +153,12 @@
boolean performHapticFeedback(int effectId, boolean always);
/**
+ * Called by attached views to perform predefined haptic feedback without requiring VIBRATE
+ * permission.
+ */
+ oneway void performHapticFeedbackAsync(int effectId, boolean always);
+
+ /**
* Initiate the drag operation itself
*
* @param window Window which initiates drag operation.
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 3e84153..e89be47 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -123,7 +123,7 @@
// TODO: ResultReceiver for IME.
// TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_REQUEST_SHOW);
if (getControl() == null) {
@@ -164,13 +164,12 @@
// - we do already have one, but we have control and use the passed in token
// for the insets animation already.
if (statsToken == null || getControl() != null) {
- statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
- Process.myUid(),
+ statsToken = ImeTracker.get().onRequestHide(null /* component */, Process.myUid(),
ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);
getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8683cc2..47da3f6 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.hardware.BatteryState;
import android.hardware.SensorManager;
+import android.hardware.input.HostUsiVersion;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.lights.LightsManager;
@@ -83,7 +84,8 @@
private final boolean mHasButtonUnderPad;
private final boolean mHasSensor;
private final boolean mHasBattery;
- private final boolean mSupportsUsi;
+ private final HostUsiVersion mHostUsiVersion;
+ private final int mAssociatedDisplayId;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
@GuardedBy("mMotionRanges")
@@ -467,7 +469,8 @@
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
KeyCharacterMap keyCharacterMap, @Nullable String keyboardLanguageTag,
@Nullable String keyboardLayoutType, boolean hasVibrator, boolean hasMicrophone,
- boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery, boolean supportsUsi) {
+ boolean hasButtonUnderPad, boolean hasSensor, boolean hasBattery, int usiVersionMajor,
+ int usiVersionMinor, int associatedDisplayId) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -493,7 +496,8 @@
mHasSensor = hasSensor;
mHasBattery = hasBattery;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
- mSupportsUsi = supportsUsi;
+ mHostUsiVersion = new HostUsiVersion(usiVersionMajor, usiVersionMinor);
+ mAssociatedDisplayId = associatedDisplayId;
}
private InputDevice(Parcel in) {
@@ -515,7 +519,8 @@
mHasButtonUnderPad = in.readInt() != 0;
mHasSensor = in.readInt() != 0;
mHasBattery = in.readInt() != 0;
- mSupportsUsi = in.readInt() != 0;
+ mHostUsiVersion = HostUsiVersion.CREATOR.createFromParcel(in);
+ mAssociatedDisplayId = in.readInt();
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
int numRanges = in.readInt();
@@ -554,7 +559,8 @@
private boolean mHasBattery = false;
private String mKeyboardLanguageTag = null;
private String mKeyboardLayoutType = null;
- private boolean mSupportsUsi = false;
+ private int mUsiVersionMajor = -1;
+ private int mUsiVersionMinor = -1;
private List<MotionRange> mMotionRanges = new ArrayList<>();
/** @see InputDevice#getId() */
@@ -665,9 +671,10 @@
return this;
}
- /** @see InputDevice#supportsUsi() () */
- public Builder setSupportsUsi(boolean supportsUsi) {
- mSupportsUsi = supportsUsi;
+ /** @see InputDevice#getHostUsiVersion() */
+ public Builder setUsiVersion(@Nullable HostUsiVersion usiVersion) {
+ mUsiVersionMajor = usiVersion != null ? usiVersion.getMajorVersion() : -1;
+ mUsiVersionMinor = usiVersion != null ? usiVersion.getMinorVersion() : -1;
return this;
}
@@ -699,7 +706,9 @@
mHasButtonUnderPad,
mHasSensor,
mHasBattery,
- mSupportsUsi);
+ mUsiVersionMajor,
+ mUsiVersionMinor,
+ Display.INVALID_DISPLAY);
final int numRanges = mMotionRanges.size();
for (int i = 0; i < numRanges; i++) {
@@ -1276,12 +1285,22 @@
}
/**
- * Reports whether the device supports the Universal Stylus Initiative (USI) protocol for
- * styluses.
+ * Reports the version of the Universal Stylus Initiative (USI) protocol supported by this
+ * input device.
+ *
+ * @return the supported USI version, or null if the device does not support USI
+ * @see <a href="https://universalstylus.org">Universal Stylus Initiative</a>
+ * @see InputManager#getHostUsiVersion(int)
* @hide
*/
- public boolean supportsUsi() {
- return mSupportsUsi;
+ @Nullable
+ public HostUsiVersion getHostUsiVersion() {
+ return mHostUsiVersion.isValid() ? mHostUsiVersion : null;
+ }
+
+ /** @hide */
+ public int getAssociatedDisplayId() {
+ return mAssociatedDisplayId;
}
/**
@@ -1415,7 +1434,8 @@
out.writeInt(mHasButtonUnderPad ? 1 : 0);
out.writeInt(mHasSensor ? 1 : 0);
out.writeInt(mHasBattery ? 1 : 0);
- out.writeInt(mSupportsUsi ? 1 : 0);
+ mHostUsiVersion.writeToParcel(out, flags);
+ out.writeInt(mAssociatedDisplayId);
int numRanges = mMotionRanges.size();
numRanges = numRanges > MAX_RANGES ? MAX_RANGES : numRanges;
@@ -1468,7 +1488,7 @@
description.append(" Has mic: ").append(mHasMicrophone).append("\n");
- description.append(" Supports USI: ").append(mSupportsUsi).append("\n");
+ description.append(" USI Version: ").append(getHostUsiVersion()).append("\n");
if (mKeyboardLanguageTag != null) {
description.append(" Keyboard language tag: ").append(mKeyboardLanguageTag).append(
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c992450..8e8e28a 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -26,7 +26,6 @@
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.ime;
-import static android.view.inputmethod.ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL;
import android.animation.AnimationHandler;
import android.animation.Animator;
@@ -36,8 +35,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityThread;
-import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -63,7 +60,6 @@
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import android.view.inputmethod.ImeTracker;
-import android.view.inputmethod.ImeTracker.InputMethodJankContext;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -190,14 +186,6 @@
@Nullable
String getRootViewTitle();
- /**
- * @return the context related to the rootView.
- */
- @Nullable
- default Context getRootViewContext() {
- return null;
- }
-
/** @see ViewRootImpl#dipToPx */
int dipToPx(int dips);
@@ -318,7 +306,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {ANIMATION_TYPE_NONE, ANIMATION_TYPE_SHOW, ANIMATION_TYPE_HIDE,
ANIMATION_TYPE_USER, ANIMATION_TYPE_RESIZE})
- public @interface AnimationType {
+ @interface AnimationType {
}
/**
@@ -333,27 +321,6 @@
/** Logging listener. */
private WindowInsetsAnimationControlListener mLoggingListener;
- /** Context for {@link android.view.inputmethod.ImeTracker.ImeJankTracker} to monitor jank. */
- private final InputMethodJankContext mJankContext = new InputMethodJankContext() {
- @Override
- public Context getDisplayContext() {
- return mHost != null ? mHost.getRootViewContext() : null;
- }
-
- @Override
- public SurfaceControl getTargetSurfaceControl() {
- final InsetsSourceConsumer imeSourceConsumer = mSourceConsumers.get(ITYPE_IME);
- final InsetsSourceControl imeSourceControl =
- imeSourceConsumer != null ? imeSourceConsumer.getControl() : null;
- return imeSourceControl != null ? imeSourceControl.getLeash() : null;
- }
-
- @Override
- public String getHostPackageName() {
- return mHost != null ? mHost.getRootViewContext().getPackageName() : null;
- }
- };
-
/**
* The default implementation of listener, to be used by InsetsController and InsetsPolicy to
* animate insets.
@@ -371,7 +338,6 @@
private final boolean mDisable;
private final int mFloatingImeBottomInset;
private final WindowInsetsAnimationControlListener mLoggingListener;
- private final InputMethodJankContext mInputMethodJankContext;
private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
new ThreadLocal<AnimationHandler>() {
@@ -385,8 +351,7 @@
public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks,
@InsetsType int requestedTypes, @Behavior int behavior, boolean disable,
- int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener,
- @Nullable InputMethodJankContext jankContext) {
+ int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) {
mShow = show;
mHasAnimationCallbacks = hasAnimationCallbacks;
mRequestedTypes = requestedTypes;
@@ -395,7 +360,6 @@
mDisable = disable;
mFloatingImeBottomInset = floatingImeBottomInset;
mLoggingListener = loggingListener;
- mInputMethodJankContext = jankContext;
}
@Override
@@ -442,26 +406,10 @@
+ insetsFraction);
});
mAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (mInputMethodJankContext == null) return;
- ImeTracker.forJank().onRequestAnimation(
- mInputMethodJankContext,
- mShow ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
- !mHasAnimationCallbacks);
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- if (mInputMethodJankContext == null) return;
- ImeTracker.forJank().onCancelAnimation();
- }
@Override
public void onAnimationEnd(Animator animation) {
onAnimationFinish();
- if (mInputMethodJankContext == null) return;
- ImeTracker.forJank().onFinishAnimation();
}
});
if (!mHasAnimationCallbacks) {
@@ -925,7 +873,7 @@
/**
* @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
- * int, android.util.SparseIntArray)
+ * int, SparseIntArray)
*/
@VisibleForTesting
public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars,
@@ -1033,7 +981,7 @@
public void show(@InsetsType int types) {
ImeTracker.Token statsToken = null;
if ((types & ime()) != 0) {
- statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
+ statsToken = ImeTracker.get().onRequestShow(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
}
@@ -1058,9 +1006,6 @@
}
// Handle pending request ready in case there was one set.
if (fromIme && mPendingImeControlRequest != null) {
- if ((types & Type.ime()) != 0) {
- ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
- }
handlePendingControlRequest(statsToken);
return;
}
@@ -1083,7 +1028,7 @@
"show ignored for type: %d animType: %d requestedVisible: %s",
type, animationType, requestedVisible));
if (isImeAnimation) {
- ImeTracker.forLogging().onCancelled(statsToken,
+ ImeTracker.get().onCancelled(statsToken,
ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
@@ -1091,21 +1036,16 @@
if (fromIme && animationType == ANIMATION_TYPE_USER) {
// App is already controlling the IME, don't cancel it.
if (isImeAnimation) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
}
if (isImeAnimation) {
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
typesReady |= type;
}
if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady);
- if (fromIme && (typesReady & Type.ime()) != 0) {
- ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication);
- }
applyAnimation(typesReady, true /* show */, fromIme, statsToken);
}
@@ -1134,7 +1074,7 @@
public void hide(@InsetsType int types) {
ImeTracker.Token statsToken = null;
if ((types & ime()) != 0) {
- statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
+ statsToken = ImeTracker.get().onRequestHide(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
@@ -1183,14 +1123,13 @@
// no-op: already hidden or animating out (because window visibility is
// applied before starting animation).
if (isImeAnimation) {
- ImeTracker.forLogging().onCancelled(statsToken,
+ ImeTracker.get().onCancelled(statsToken,
ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
continue;
}
if (isImeAnimation) {
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_APPLY_ANIMATION);
}
typesReady |= type;
}
@@ -1262,19 +1201,8 @@
@AnimationType int animationType,
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION);
if ((types & mTypesBeingCancelled) != 0) {
- final boolean monitoredAnimation =
- animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE;
- if (monitoredAnimation && (types & Type.ime()) != 0) {
- if (animationType == ANIMATION_TYPE_SHOW) {
- ImeTracker.forLatency().onShowCancelled(statsToken,
- PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
- } else {
- ImeTracker.forLatency().onHideCancelled(statsToken,
- PHASE_CLIENT_ANIMATION_CANCEL, ActivityThread::currentApplication);
- }
- }
throw new IllegalStateException("Cannot start a new insets animation of "
+ Type.toString(types)
+ " while an existing " + Type.toString(mTypesBeingCancelled)
@@ -1286,7 +1214,7 @@
types &= ~mDisabledUserAnimationInsetsTypes;
if ((disabledTypes & ime()) != 0) {
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
if (fromIme && !mState.getSource(mImeSourceConsumer.getId()).isVisible()) {
@@ -1307,8 +1235,7 @@
Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
return;
}
- ImeTracker.forLogging().onProgress(statsToken,
- ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);
if (DEBUG) Log.d(TAG, "controlAnimation types: " + types);
mLastStartedAnimTypes |= types;
@@ -1375,11 +1302,8 @@
if ((typesReady & WindowInsets.Type.ime()) != 0) {
ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl",
mHost.getInputMethodManager(), null /* icProto */);
- if (animationType == ANIMATION_TYPE_HIDE) {
- ImeTracker.forLatency().onHidden(statsToken, ActivityThread::currentApplication);
- }
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_RUNNING);
mRunningAnimations.add(new RunningAnimation(runner, animationType));
if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
+ useInsetsAnimationThread);
@@ -1419,8 +1343,7 @@
private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, @InsetsType int types,
SparseArray<InsetsSourceControl> controls, @AnimationType int animationType,
@Nullable ImeTracker.Token statsToken) {
- ImeTracker.forLogging().onProgress(statsToken,
- ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS);
int typesReady = 0;
boolean imeReady = true;
@@ -1523,13 +1446,13 @@
}
final ImeTracker.Token statsToken = runner.getStatsToken();
if (shown) {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW);
- ImeTracker.forLogging().onShown(statsToken);
+ ImeTracker.get().onShown(statsToken);
} else {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE);
- ImeTracker.forLogging().onHidden(statsToken);
+ ImeTracker.get().onHidden(statsToken);
}
reportRequestedVisibleTypes();
}
@@ -1555,13 +1478,13 @@
private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
if (invokeCallback) {
- ImeTracker.forLogging().onCancelled(control.getStatsToken(),
- PHASE_CLIENT_ANIMATION_CANCEL);
+ ImeTracker.get().onCancelled(control.getStatsToken(),
+ ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
control.cancel();
} else {
// Succeeds if invokeCallback is false (i.e. when called from notifyFinished).
- ImeTracker.forLogging().onProgress(control.getStatsToken(),
- PHASE_CLIENT_ANIMATION_CANCEL);
+ ImeTracker.get().onProgress(control.getStatsToken(),
+ ImeTracker.PHASE_CLIENT_ANIMATION_CANCEL);
}
if (DEBUG) {
Log.d(TAG, TextUtils.formatSimple(
@@ -1726,7 +1649,7 @@
final InternalAnimationControlListener listener = new InternalAnimationControlListener(
show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(),
skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP),
- mLoggingListener, mJankContext);
+ mLoggingListener);
// We are about to playing the default animation (show/hide). Passing a null frame indicates
// the controlled types should be animated regardless of the frame.
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 84bbdd1..a71ab8a 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -2322,6 +2322,29 @@
}
/**
+ * Returns {@code true} if this motion event is from a stylus pointer.
+ * @hide
+ */
+ public boolean isStylusPointer() {
+ final int actionIndex = getActionIndex();
+ return isFromSource(InputDevice.SOURCE_STYLUS)
+ && (getToolType(actionIndex) == TOOL_TYPE_STYLUS
+ || getToolType(actionIndex) == TOOL_TYPE_ERASER);
+ }
+
+ /**
+ * Returns {@code true} if this motion event is a hover event, identified by it having an action
+ * of either {@link #ACTION_HOVER_ENTER}, {@link #ACTION_HOVER_MOVE} or
+ * {@link #ACTION_HOVER_EXIT}.
+ * @hide
+ */
+ public boolean isHoverEvent() {
+ return getActionMasked() == ACTION_HOVER_ENTER
+ || getActionMasked() == ACTION_HOVER_EXIT
+ || getActionMasked() == ACTION_HOVER_MOVE;
+ }
+
+ /**
* Gets the motion event flags.
*
* @see #FLAG_WINDOW_IS_OBSCURED
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 080c0d8..6a493e6 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -138,6 +138,9 @@
/** Type constant: grabbing. */
public static final int TYPE_GRABBING = 1021;
+ /** Type constant: handwriting. */
+ public static final int TYPE_HANDWRITING = 1022;
+
// OEM private types should be defined starting at this range to avoid
// conflicts with any system types that may be defined in the future.
private static final int TYPE_OEM_FIRST = 10000;
@@ -601,6 +604,8 @@
return com.android.internal.R.styleable.Pointer_pointerIconGrab;
case TYPE_GRABBING:
return com.android.internal.R.styleable.Pointer_pointerIconGrabbing;
+ case TYPE_HANDWRITING:
+ return com.android.internal.R.styleable.Pointer_pointerIconHandwriting;
default:
return 0;
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 3efbb75..f6348d7 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -485,7 +485,6 @@
* SurfaceControlViewHost was created with an associated hostInputToken.
*
* @return Whether the touch stream was transferred.
- * @hide
*/
public boolean transferTouchGestureToHost() {
if (mViewRoot == null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2763607..5dccd06 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -70,6 +70,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -279,6 +280,14 @@
private static final boolean ENABLE_INPUT_LATENCY_TRACKING = true;
/**
+ * Controls whether to use the new oneway performHapticFeedback call. This returns
+ * true in a few more conditions, but doesn't affect which haptics happen. Notably, it
+ * makes the call to performHapticFeedback non-blocking, which reduces potential UI jank.
+ * This is intended as a temporary flag, ultimately becoming permanently 'true'.
+ */
+ private static final boolean USE_ASYNC_PERFORM_HAPTIC_FEEDBACK = true;
+
+ /**
* Whether the caption is drawn by the shell.
* @hide
*/
@@ -2781,7 +2790,7 @@
* TODO(b/260382739): Apply this to all windows.
*/
private static boolean shouldOptimizeMeasure(final WindowManager.LayoutParams lp) {
- return lp.type == TYPE_NOTIFICATION_SHADE;
+ return (lp.privateFlags & PRIVATE_FLAG_OPTIMIZE_MEASURE) != 0;
}
private Rect getWindowBoundsInsetSystemBars() {
@@ -5764,7 +5773,7 @@
}
case MSG_SHOW_INSETS: {
final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_HANDLE_SHOW_INSETS);
if (mView == null) {
Log.e(TAG,
@@ -5777,7 +5786,7 @@
}
case MSG_HIDE_INSETS: {
final ImeTracker.Token statsToken = (ImeTracker.Token) msg.obj;
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_CLIENT_HANDLE_HIDE_INSETS);
mInsetsController.hide(msg.arg1, msg.arg2 == 1, statsToken);
break;
@@ -6835,7 +6844,13 @@
}
private void maybeUpdatePointerIcon(MotionEvent event) {
- if (event.getPointerCount() == 1 && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+ if (event.getPointerCount() != 1) {
+ return;
+ }
+ final boolean needsStylusPointerIcon =
+ InputManager.getInstance().isStylusPointerIconEnabled()
+ && event.isStylusPointer();
+ if (needsStylusPointerIcon || event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
|| event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
// Other apps or the window manager may change the icon type outside of
@@ -6903,7 +6918,17 @@
Slog.d(mTag, "updatePointerIcon called with position out of bounds");
return false;
}
- final PointerIcon pointerIcon = mView.onResolvePointerIcon(event, pointerIndex);
+
+ PointerIcon pointerIcon = null;
+
+ if (event.isStylusPointer() && InputManager.getInstance().isStylusPointerIconEnabled()) {
+ pointerIcon = mHandwritingInitiator.onResolvePointerIcon(mContext, event);
+ }
+
+ if (pointerIcon == null) {
+ pointerIcon = mView.onResolvePointerIcon(event, pointerIndex);
+ }
+
final int pointerType = (pointerIcon != null) ?
pointerIcon.getType() : PointerIcon.TYPE_DEFAULT;
@@ -8566,7 +8591,13 @@
}
try {
- return mWindowSession.performHapticFeedback(effectId, always);
+ if (USE_ASYNC_PERFORM_HAPTIC_FEEDBACK) {
+ mWindowSession.performHapticFeedbackAsync(effectId, always);
+ return true;
+ } else {
+ // Original blocking binder call path.
+ return mWindowSession.performHapticFeedback(effectId, always);
+ }
} catch (RemoteException e) {
return false;
}
@@ -10324,10 +10355,10 @@
null /* icProto */);
}
if (viewAncestor != null) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
viewAncestor.showInsets(types, fromIme, statsToken);
} else {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_SHOW_INSETS);
}
}
@@ -10341,10 +10372,10 @@
null /* icProto */);
}
if (viewAncestor != null) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
viewAncestor.hideInsets(types, fromIme, statsToken);
} else {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_HIDE_INSETS);
}
}
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 037ce87..c59d83e 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -21,7 +21,6 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import android.annotation.NonNull;
-import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.os.Handler;
import android.os.IBinder;
@@ -247,11 +246,6 @@
}
@Override
- public Context getRootViewContext() {
- return mViewRoot != null ? mViewRoot.getView().getContext() : null;
- }
-
- @Override
public int dipToPx(int dips) {
if (mViewRoot != null) {
return mViewRoot.dipToPx(dips);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 35f1787..e437c1f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2663,6 +2663,15 @@
public static final int PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100;
/**
+ * Flag to indicate that the view hierarchy of the window can only be measured when
+ * necessary. If a window size can be known by the LayoutParams, we can use the size to
+ * relayout window, and we don't have to measure the view hierarchy before laying out the
+ * views. This reduces the chances to perform measure.
+ * {@hide}
+ */
+ public static final int PRIVATE_FLAG_OPTIMIZE_MEASURE = 0x00000200;
+
+ /**
* Flag that prevents the wallpaper behind the current window from receiving touch events.
*
* {@hide}
@@ -2864,6 +2873,7 @@
PRIVATE_FLAG_NO_MOVE_ANIMATION,
PRIVATE_FLAG_COMPATIBLE_WINDOW,
PRIVATE_FLAG_SYSTEM_ERROR,
+ PRIVATE_FLAG_OPTIMIZE_MEASURE,
PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS,
PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR,
PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT,
@@ -2924,6 +2934,10 @@
equals = PRIVATE_FLAG_SYSTEM_ERROR,
name = "SYSTEM_ERROR"),
@ViewDebug.FlagToString(
+ mask = PRIVATE_FLAG_OPTIMIZE_MEASURE,
+ equals = PRIVATE_FLAG_OPTIMIZE_MEASURE,
+ name = "OPTIMIZE_MEASURE"),
+ @ViewDebug.FlagToString(
mask = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS,
equals = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS,
name = "DISABLE_WALLPAPER_TOUCH_EVENTS"),
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 4ddd485..7d37c50 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -466,6 +466,11 @@
}
@Override
+ public void performHapticFeedbackAsync(int effectId, boolean always) {
+ performHapticFeedback(effectId, always);
+ }
+
+ @Override
public android.os.IBinder performDrag(android.view.IWindow window, int flags,
android.view.SurfaceControl surface, int touchSource, float touchX, float touchY,
float thumbCenterX, float thumbCenterY, android.content.ClipData data) {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 2ad01ed..b5764c5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1235,6 +1235,42 @@
}
/**
+ * Called when the virtual views are ready to the user for autofill.
+ *
+ * This method is used to notify autofill system the views are ready to the user. And then
+ * Autofill can do initialization if needed before the user starts to input. For example, do
+ * a pre-fill request for the
+ * <a href="/reference/android/service/autofill/Dataset.html#FillDialogUI">fill dialog</a>.
+ *
+ * @param view the host view that holds a virtual view hierarchy.
+ * @param infos extra information for the virtual views. The key is virtual id which represents
+ * the virtual view in the host view.
+ *
+ * @throws IllegalArgumentException if the {@code infos} was empty
+ */
+ public void notifyVirtualViewsReady(
+ @NonNull View view, @NonNull SparseArray<VirtualViewFillInfo> infos) {
+ Objects.requireNonNull(infos);
+ if (infos.size() == 0) {
+ throw new IllegalArgumentException("No VirtualViewInfo found");
+ }
+ if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager()
+ && view.isCredential()) {
+ if (sDebug) {
+ Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
+ + view.getAutofillId().toString());
+ }
+ return;
+ }
+ for (int i = 0; i < infos.size(); i++) {
+ final VirtualViewFillInfo info = infos.valueAt(i);
+ final int virtualId = infos.indexOfKey(i);
+ notifyViewReadyInner(getAutofillId(view, virtualId),
+ (info == null) ? null : info.getAutofillHints());
+ }
+ }
+
+ /**
* The {@link AutofillFeatureFlags#DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or
* the view have the allowed autofill hints, performs a fill request to know there is any field
* supported fill dialog.
@@ -1245,9 +1281,6 @@
if (sDebug) {
Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId());
}
- if (!hasAutofillFeature()) {
- return;
- }
if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager()
&& v.isCredential()) {
if (sDebug) {
@@ -1256,6 +1289,13 @@
}
return;
}
+ notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints());
+ }
+
+ private void notifyViewReadyInner(AutofillId id, String[] autofillHints) {
+ if (!hasAutofillFeature()) {
+ return;
+ }
synchronized (mLock) {
if (mTrackedViews != null) {
@@ -1263,7 +1303,7 @@
// different pages but in the same Activity. We need to reset the
// mIsFillRequested flag to allow asking for a new FillRequest when
// user switches to other page
- mTrackedViews.checkViewState(v.getAutofillId());
+ mTrackedViews.checkViewState(id);
}
}
@@ -1273,9 +1313,9 @@
}
if (mIsFillDialogEnabled
- || ArrayUtils.containsAny(v.getAutofillHints(), mFillDialogEnabledHints)) {
+ || ArrayUtils.containsAny(autofillHints, mFillDialogEnabledHints)) {
if (sDebug) {
- Log.d(TAG, "Trigger fill request at view entered");
+ Log.d(TAG, "Trigger fill request when the view is ready.");
}
int flags = FLAG_SUPPORTS_FILL_DIALOG;
diff --git a/core/java/android/view/autofill/VirtualViewFillInfo.java b/core/java/android/view/autofill/VirtualViewFillInfo.java
new file mode 100644
index 0000000..4bec5a4
--- /dev/null
+++ b/core/java/android/view/autofill/VirtualViewFillInfo.java
@@ -0,0 +1,141 @@
+/*
+ * 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 android.view.autofill;
+
+
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.view.View;
+
+import com.android.internal.util.DataClass;
+
+
+/**
+ * Information for the virtual view to the autofill framework.
+ */
+@DataClass(genBuilder = true)
+public final class VirtualViewFillInfo {
+
+ /**
+ * Autofill hints of the virtual view.
+ *
+ * @see View#setAutofillHints(String...)
+ */
+ @Nullable
+ @SuppressLint("NullableCollection")
+ private String[] mAutofillHints;
+
+ private static String[] defaultAutofillHints() {
+ return null;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/autofill/VirtualViewFillInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ VirtualViewFillInfo(
+ @Nullable @SuppressLint("NullableCollection") String[] autofillHints) {
+ this.mAutofillHints = autofillHints;
+ com.android.internal.util.AnnotationValidations.validate(
+ SuppressLint.class, null, mAutofillHints,
+ "value", "NullableCollection");
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Autofill hints of the virtual view.
+ *
+ * @see View#setAutofillHints(String...)
+ */
+ @DataClass.Generated.Member
+ public @Nullable @SuppressLint("NullableCollection") String[] getAutofillHints() {
+ return mAutofillHints;
+ }
+
+ /**
+ * A builder for {@link VirtualViewFillInfo}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private @Nullable @SuppressLint("NullableCollection") String[] mAutofillHints;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * Autofill hints of the virtual view.
+ *
+ * @see View#setAutofillHints(String...)
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull Builder setAutofillHints(@SuppressLint("NullableCollection") @android.annotation.NonNull String... value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mAutofillHints = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @android.annotation.NonNull VirtualViewFillInfo build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mAutofillHints = defaultAutofillHints();
+ }
+ VirtualViewFillInfo o = new VirtualViewFillInfo(
+ mAutofillHints);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x2) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1674023010954L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/view/autofill/VirtualViewFillInfo.java",
+ inputSignatures = "private @android.annotation.Nullable @android.annotation.SuppressLint java.lang.String[] mAutofillHints\nprivate static java.lang.String[] defaultAutofillHints()\nclass VirtualViewFillInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 9ebaa67..4e5cec7 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -568,6 +568,8 @@
supportedTypes |= HandwritingGesture.GESTURE_TYPE_SELECT_RANGE;
} else if (gesture.equals(InsertGesture.class)) {
supportedTypes |= HandwritingGesture.GESTURE_TYPE_INSERT;
+ } else if (gesture.equals(InsertModeGesture.class)) {
+ supportedTypes |= HandwritingGesture.GESTURE_TYPE_INSERT_MODE;
} else if (gesture.equals(DeleteGesture.class)) {
supportedTypes |= HandwritingGesture.GESTURE_TYPE_DELETE;
} else if (gesture.equals(DeleteRangeGesture.class)) {
@@ -611,6 +613,10 @@
== HandwritingGesture.GESTURE_TYPE_INSERT) {
list.add(InsertGesture.class);
}
+ if ((mSupportedHandwritingGestureTypes & HandwritingGesture.GESTURE_TYPE_INSERT_MODE)
+ == HandwritingGesture.GESTURE_TYPE_INSERT_MODE) {
+ list.add(InsertModeGesture.class);
+ }
if ((mSupportedHandwritingGestureTypes & HandwritingGesture.GESTURE_TYPE_DELETE)
== HandwritingGesture.GESTURE_TYPE_DELETE) {
list.add(DeleteGesture.class);
diff --git a/core/java/android/view/inputmethod/HandwritingGesture.java b/core/java/android/view/inputmethod/HandwritingGesture.java
index 1f4a7af..e7207fa 100644
--- a/core/java/android/view/inputmethod/HandwritingGesture.java
+++ b/core/java/android/view/inputmethod/HandwritingGesture.java
@@ -142,6 +142,13 @@
public static final int GESTURE_TYPE_DELETE_RANGE = 1 << 6;
/**
+ * Gesture of type {@link InsertModeGesture} to begin an insert mode at a designated point.
+ * @hide
+ */
+ @TestApi
+ public static final int GESTURE_TYPE_INSERT_MODE = 1 << 7;
+
+ /**
* Type of gesture like {@link #GESTURE_TYPE_SELECT}, {@link #GESTURE_TYPE_INSERT},
* or {@link #GESTURE_TYPE_DELETE}.
*/
@@ -150,6 +157,7 @@
GESTURE_TYPE_SELECT,
GESTURE_TYPE_SELECT_RANGE,
GESTURE_TYPE_INSERT,
+ GESTURE_TYPE_INSERT_MODE,
GESTURE_TYPE_DELETE,
GESTURE_TYPE_DELETE_RANGE,
GESTURE_TYPE_REMOVE_SPACE,
@@ -168,6 +176,7 @@
GESTURE_TYPE_SELECT,
GESTURE_TYPE_SELECT_RANGE,
GESTURE_TYPE_INSERT,
+ GESTURE_TYPE_INSERT_MODE,
GESTURE_TYPE_DELETE,
GESTURE_TYPE_DELETE_RANGE,
GESTURE_TYPE_REMOVE_SPACE,
diff --git a/core/java/android/view/inputmethod/ImeTracker.java b/core/java/android/view/inputmethod/ImeTracker.java
index a07dedc..3b6ec80 100644
--- a/core/java/android/view/inputmethod/ImeTracker.java
+++ b/core/java/android/view/inputmethod/ImeTracker.java
@@ -16,36 +16,24 @@
package android.view.inputmethod;
-import static com.android.internal.inputmethod.InputMethodDebug.softInputDisplayReasonToString;
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_IME_INSETS_ANIMATION;
-import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_HIDDEN;
-import static com.android.internal.util.LatencyTracker.ACTION_REQUEST_IME_SHOWN;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
-import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.util.Log;
-import android.view.InsetsController.AnimationType;
-import android.view.SurfaceControl;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.jank.InteractionJankMonitor.Configuration;
-import com.android.internal.util.LatencyTracker;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
@@ -397,35 +385,15 @@
void onHidden(@Nullable Token token);
/**
- * Get the singleton request tracker instance.
+ * Get the singleton instance of this class.
*
- * @return the singleton request tracker instance
+ * @return the singleton instance of this class
*/
@NonNull
- static ImeTracker forLogging() {
+ static ImeTracker get() {
return LOGGER;
}
- /**
- * Get the singleton jank tracker instance.
- *
- * @return the singleton jank tracker instance
- */
- @NonNull
- static ImeJankTracker forJank() {
- return JANK_TRACKER;
- }
-
- /**
- * Get the singleton latency tracker instance.
- *
- * @return the singleton latency tracker instance
- */
- @NonNull
- static ImeLatencyTracker forLatency() {
- return LATENCY_TRACKER;
- }
-
/** The singleton IME tracker instance. */
@NonNull
ImeTracker LOGGER = new ImeTracker() {
@@ -521,12 +489,6 @@
}
};
- /** The singleton IME tracker instance for instrumenting jank metrics. */
- ImeJankTracker JANK_TRACKER = new ImeJankTracker();
-
- /** The singleton IME tracker instance for instrumenting latency metrics. */
- ImeLatencyTracker LATENCY_TRACKER = new ImeLatencyTracker();
-
/** A token that tracks the progress of an IME request. */
class Token implements Parcelable {
@@ -630,153 +592,4 @@
}
}
}
-
- /**
- * Context related to {@link InteractionJankMonitor}.
- */
- interface InputMethodJankContext {
- /**
- * @return a context associated with a display
- */
- Context getDisplayContext();
-
- /**
- * @return a SurfaceControl is going to be monitored
- */
- SurfaceControl getTargetSurfaceControl();
-
- /**
- * @return the package name of the host
- */
- String getHostPackageName();
- }
-
- /**
- * Context related to {@link LatencyTracker}.
- */
- interface InputMethodLatencyContext {
- /**
- * @return a context associated with current application
- */
- Context getAppContext();
- }
-
- /**
- * A tracker instance which is in charge of communicating with {@link InteractionJankMonitor}.
- */
- final class ImeJankTracker {
-
- private ImeJankTracker() {
- }
-
- /**
- * Called when the animation, which is going to be monitored, starts.
- *
- * @param jankContext context which is needed by {@link InteractionJankMonitor}
- * @param animType {@link AnimationType}
- * @param useSeparatedThread {@code true} if the animation is handled by the app,
- * {@code false} if the animation will be scheduled on the
- * {@link android.view.InsetsAnimationThread}
- */
- public void onRequestAnimation(@NonNull InputMethodJankContext jankContext,
- @AnimationType int animType, boolean useSeparatedThread) {
- if (jankContext.getDisplayContext() == null
- || jankContext.getTargetSurfaceControl() == null) {
- return;
- }
- final Configuration.Builder builder = Configuration.Builder.withSurface(
- CUJ_IME_INSETS_ANIMATION,
- jankContext.getDisplayContext(),
- jankContext.getTargetSurfaceControl())
- .setTag(String.format(Locale.US, "%d@%d@%s", animType,
- useSeparatedThread ? 0 : 1, jankContext.getHostPackageName()));
- InteractionJankMonitor.getInstance().begin(builder);
- }
-
- /**
- * Called when the animation, which is going to be monitored, cancels.
- */
- public void onCancelAnimation() {
- InteractionJankMonitor.getInstance().cancel(CUJ_IME_INSETS_ANIMATION);
- }
-
- /**
- * Called when the animation, which is going to be monitored, ends.
- */
- public void onFinishAnimation() {
- InteractionJankMonitor.getInstance().end(CUJ_IME_INSETS_ANIMATION);
- }
- }
-
- /**
- * A tracker instance which is in charge of communicating with {@link LatencyTracker}.
- */
- final class ImeLatencyTracker {
-
- private ImeLatencyTracker() {
- }
-
- private boolean shouldMonitorLatency(@SoftInputShowHideReason int reason) {
- return reason == SoftInputShowHideReason.SHOW_SOFT_INPUT
- || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT
- || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API
- || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API
- || reason == SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME
- || reason == SoftInputShowHideReason.HIDE_SOFT_INPUT_FROM_IME;
- }
-
- public void onRequestShow(@Nullable Token token, @Origin int origin,
- @SoftInputShowHideReason int reason,
- @NonNull InputMethodLatencyContext latencyContext) {
- if (!shouldMonitorLatency(reason)) return;
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionStart(
- ACTION_REQUEST_IME_SHOWN,
- softInputDisplayReasonToString(reason));
- }
-
- public void onRequestHide(@Nullable Token token, @Origin int origin,
- @SoftInputShowHideReason int reason,
- @NonNull InputMethodLatencyContext latencyContext) {
- if (!shouldMonitorLatency(reason)) return;
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionStart(
- ACTION_REQUEST_IME_HIDDEN,
- softInputDisplayReasonToString(reason));
- }
-
- public void onShowFailed(@Nullable Token token, @Phase int phase,
- @NonNull InputMethodLatencyContext latencyContext) {
- onShowCancelled(token, phase, latencyContext);
- }
-
- public void onHideFailed(@Nullable Token token, @Phase int phase,
- @NonNull InputMethodLatencyContext latencyContext) {
- onHideCancelled(token, phase, latencyContext);
- }
-
- public void onShowCancelled(@Nullable Token token, @Phase int phase,
- @NonNull InputMethodLatencyContext latencyContext) {
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionCancel(ACTION_REQUEST_IME_SHOWN);
- }
-
- public void onHideCancelled(@Nullable Token token, @Phase int phase,
- @NonNull InputMethodLatencyContext latencyContext) {
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionCancel(ACTION_REQUEST_IME_HIDDEN);
- }
-
- public void onShown(@Nullable Token token,
- @NonNull InputMethodLatencyContext latencyContext) {
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionEnd(ACTION_REQUEST_IME_SHOWN);
- }
-
- public void onHidden(@Nullable Token token,
- @NonNull InputMethodLatencyContext latencyContext) {
- LatencyTracker.getInstance(latencyContext.getAppContext())
- .onActionEnd(ACTION_REQUEST_IME_HIDDEN);
- }
- }
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 642182b..99bd02d 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2045,11 +2045,10 @@
private boolean showSoftInput(View view, @Nullable ImeTracker.Token statsToken, int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
if (statsToken == null) {
- statsToken = ImeTracker.forLogging().onRequestShow(null /* component */,
+ statsToken = ImeTracker.get().onRequestShow(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT, reason);
}
- ImeTracker.forLatency().onRequestShow(statsToken, ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
- reason, ActivityThread::currentApplication);
+
ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this,
null /* icProto */);
// Re-dispatch if there is a context mismatch.
@@ -2061,15 +2060,12 @@
checkFocus();
synchronized (mH) {
if (!hasServedByInputMethodLocked(view)) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
- ImeTracker.forLatency().onShowFailed(
- statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED,
- ActivityThread::currentApplication);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
Log.w(TAG, "Ignoring showSoftInput() as view=" + view + " is not served.");
return false;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
// Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
// TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2099,20 +2095,20 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
synchronized (mH) {
- final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestShow(
- null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
+ final ImeTracker.Token statsToken = ImeTracker.get().onRequestShow(null /* component */,
+ Process.myUid(), ImeTracker.ORIGIN_CLIENT_SHOW_SOFT_INPUT,
SoftInputShowHideReason.SHOW_SOFT_INPUT);
Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be"
+ " removed soon. If you are using androidx.appcompat.widget.SearchView,"
+ " please update to version 26.0 or newer version.");
if (mCurRootView == null || mCurRootView.getView() == null) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
return;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
// Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
// TODO(b/229426865): call WindowInsetsController#show instead.
@@ -2190,24 +2186,20 @@
private boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
- final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
- null /* component */, Process.myUid(),
- ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
- ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
- reason, ActivityThread::currentApplication);
+ final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
+ Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT, reason);
+
ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow",
this, null /* icProto */);
checkFocus();
synchronized (mH) {
final View servedView = getServedViewLocked();
if (servedView == null || servedView.getWindowToken() != windowToken) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
- ImeTracker.forLatency().onHideFailed(statsToken,
- ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
return false;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
flags, resultReceiver, reason);
@@ -2843,22 +2835,18 @@
@UnsupportedAppUsage
void closeCurrentInput() {
- final ImeTracker.Token statsToken = ImeTracker.forLogging().onRequestHide(
- null /* component */, Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
+ final ImeTracker.Token statsToken = ImeTracker.get().onRequestHide(null /* component */,
+ Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT);
- ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
- SoftInputShowHideReason.HIDE_SOFT_INPUT, ActivityThread::currentApplication);
synchronized (mH) {
if (mCurRootView == null || mCurRootView.getView() == null) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
- ImeTracker.forLatency().onHideFailed(statsToken,
- ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
return;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
IInputMethodManagerGlobalInvoker.hideSoftInput(
mClient,
@@ -2917,13 +2905,11 @@
synchronized (mH) {
final View servedView = getServedViewLocked();
if (servedView == null || servedView.getWindowToken() != windowToken) {
- ImeTracker.forLogging().onFailed(statsToken,
- ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
return false;
}
- ImeTracker.forLogging().onProgress(statsToken,
- ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_REQUEST_IME_SHOW);
showSoftInput(servedView, statsToken, 0 /* flags */, null /* resultReceiver */,
SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API);
@@ -2941,25 +2927,21 @@
*/
public void notifyImeHidden(IBinder windowToken, @Nullable ImeTracker.Token statsToken) {
if (statsToken == null) {
- statsToken = ImeTracker.forLogging().onRequestHide(null /* component */,
+ statsToken = ImeTracker.get().onRequestHide(null /* component */,
Process.myUid(), ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
}
- ImeTracker.forLatency().onRequestHide(statsToken, ImeTracker.ORIGIN_CLIENT_HIDE_SOFT_INPUT,
- SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API,
- ActivityThread::currentApplication);
+
ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this,
null /* icProto */);
synchronized (mH) {
if (!isImeSessionAvailableLocked() || mCurRootView == null
|| mCurRootView.getWindowToken() != windowToken) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
- ImeTracker.forLatency().onHideFailed(statsToken,
- ImeTracker.PHASE_CLIENT_VIEW_SERVED, ActivityThread::currentApplication);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
return;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_VIEW_SERVED);
IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, statsToken,
0 /* flags */, null /* resultReceiver */,
diff --git a/core/java/android/view/inputmethod/InsertModeGesture.aidl b/core/java/android/view/inputmethod/InsertModeGesture.aidl
new file mode 100644
index 0000000..a0790b8
--- /dev/null
+++ b/core/java/android/view/inputmethod/InsertModeGesture.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable InsertModeGesture;
\ No newline at end of file
diff --git a/core/java/android/view/inputmethod/InsertModeGesture.java b/core/java/android/view/inputmethod/InsertModeGesture.java
new file mode 100644
index 0000000..6b9d7fb
--- /dev/null
+++ b/core/java/android/view/inputmethod/InsertModeGesture.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.graphics.PointF;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import java.util.Objects;
+
+/**
+ * A sub-class of {@link HandwritingGesture} for starting an insert mode which inserts a space in
+ * the editor to let users hand write freely at the designated insertion point.
+ * This class holds the information required for insertion of text in
+ * toolkit widgets like {@link TextView}.
+ *
+ * Once InsertMode gesture is started, it continues until IME calls
+ * {@link CancellationSignal#cancel()} and toolkit can receive cancel using
+ * {@link CancellationSignal#setOnCancelListener(CancellationSignal.OnCancelListener)} obtained from
+ * {@link #getCancellationSignal()}.
+ */
+public final class InsertModeGesture extends HandwritingGesture implements Parcelable {
+
+ private PointF mPoint;
+ private CancellationSignal mCancellationSignal;
+
+ private InsertModeGesture(PointF point, String fallbackText,
+ CancellationSignal cancellationSignal) {
+ mType = GESTURE_TYPE_INSERT_MODE;
+ mPoint = point;
+ mFallbackText = fallbackText;
+ mCancellationSignal = cancellationSignal;
+ }
+
+ private InsertModeGesture(final Parcel source) {
+ mType = GESTURE_TYPE_INSERT_MODE;
+ mFallbackText = source.readString8();
+ mPoint = source.readTypedObject(PointF.CREATOR);
+ }
+
+ /**
+ * Returns the {@link CancellationSignal} associated with finishing this gesture.
+ * Once InsertMode gesture is started, it continues until IME calls
+ * {@link CancellationSignal#cancel()} and toolkit can receive cancel using
+ * {@link CancellationSignal#setOnCancelListener(CancellationSignal.OnCancelListener)}.
+ */
+ @NonNull
+ public CancellationSignal getCancellationSignal() {
+ return mCancellationSignal;
+ }
+
+ /**
+ * Returns the insertion point {@link PointF} (in screen coordinates) where space will be
+ * created for additional text to be inserted.
+ */
+ @NonNull
+ public PointF getInsertionPoint() {
+ return mPoint;
+ }
+
+ /**
+ * Builder for {@link InsertModeGesture}. This class is not designed to be thread-safe.
+ */
+ public static final class Builder {
+ private PointF mPoint;
+ private String mFallbackText;
+ // TODO(b/254727073): implement CancellationSignal
+ private CancellationSignal mCancellationSignal;
+
+ /**
+ * Sets the insertion point (in screen coordinates) where space will be created for
+ * additional text to be inserted.
+ */
+ @NonNull
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setInsertionPoint(@NonNull PointF point) {
+ mPoint = point;
+ return this;
+ }
+
+ /**
+ * Sets the {@link CancellationSignal} used to cancel the ongoing gesture.
+ * @param cancellationSignal signal to cancel an ongoing gesture.
+ */
+ @NonNull
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setCancellationSignal(@NonNull CancellationSignal cancellationSignal) {
+ mCancellationSignal = cancellationSignal;
+ return this;
+ }
+
+ /**
+ * Set fallback text that will be committed at current cursor position if there is no
+ * applicable text beneath the area of gesture.
+ * @param fallbackText text to set
+ */
+ @NonNull
+ public Builder setFallbackText(@Nullable String fallbackText) {
+ mFallbackText = fallbackText;
+ return this;
+ }
+
+ /**
+ * Returns {@link InsertModeGesture} using parameters in this
+ * {@link InsertModeGesture.Builder}.
+ * @throws IllegalArgumentException if one or more positional parameters are not specified.
+ */
+ @NonNull
+ public InsertModeGesture build() {
+ if (mPoint == null) {
+ throw new IllegalArgumentException("Insertion point must be set.");
+ } else if (mCancellationSignal == null) {
+ throw new IllegalArgumentException("CancellationSignal must be set.");
+ }
+ return new InsertModeGesture(mPoint, mFallbackText, mCancellationSignal);
+ }
+ }
+
+ /**
+ * Used to make this class parcelable.
+ */
+ @NonNull
+ public static final Creator<InsertModeGesture> CREATOR = new Creator<>() {
+ @Override
+ public InsertModeGesture createFromParcel(Parcel source) {
+ return new InsertModeGesture(source);
+ }
+
+ @Override
+ public InsertModeGesture[] newArray(int size) {
+ return new InsertModeGesture[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPoint, mFallbackText);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof InsertModeGesture)) return false;
+
+ InsertModeGesture that = (InsertModeGesture) o;
+
+ if (!Objects.equals(mFallbackText, that.mFallbackText)) return false;
+ return Objects.equals(mPoint, that.mPoint);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mFallbackText);
+ dest.writeTypedObject(mPoint, flags);
+ }
+}
diff --git a/core/java/android/view/inputmethod/ParcelableHandwritingGesture.java b/core/java/android/view/inputmethod/ParcelableHandwritingGesture.java
index e4066fc..ae7df0f 100644
--- a/core/java/android/view/inputmethod/ParcelableHandwritingGesture.java
+++ b/core/java/android/view/inputmethod/ParcelableHandwritingGesture.java
@@ -70,6 +70,8 @@
return SelectRangeGesture.CREATOR.createFromParcel(parcel);
case HandwritingGesture.GESTURE_TYPE_INSERT:
return InsertGesture.CREATOR.createFromParcel(parcel);
+ case HandwritingGesture.GESTURE_TYPE_INSERT_MODE:
+ return InsertModeGesture.CREATOR.createFromParcel(parcel);
case HandwritingGesture.GESTURE_TYPE_DELETE:
return DeleteGesture.CREATOR.createFromParcel(parcel);
case HandwritingGesture.GESTURE_TYPE_DELETE_RANGE:
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 95a42aa..f2f4557 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -73,10 +73,12 @@
import android.text.SpannedString;
import android.text.StaticLayout;
import android.text.TextUtils;
+import android.text.method.InsertModeTransformationMethod;
import android.text.method.KeyListener;
import android.text.method.MetaKeyKeyListener;
import android.text.method.MovementMethod;
import android.text.method.OffsetMapping;
+import android.text.method.TransformationMethod;
import android.text.method.WordIterator;
import android.text.style.EasyEditSpan;
import android.text.style.SuggestionRangeSpan;
@@ -136,6 +138,7 @@
import android.window.OnBackInvokedDispatcher;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.inputmethod.EditableInputConnection;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -461,6 +464,7 @@
private int mLineChangeSlopMin;
private final AccessibilitySmartActions mA11ySmartActions;
+ private InsertModeController mInsertModeController;
Editor(TextView textView) {
mTextView = textView;
@@ -2109,6 +2113,10 @@
}
}
+ if (mInsertModeController != null) {
+ mInsertModeController.onDraw(canvas);
+ }
+
if (mTextView.canHaveDisplayList() && canvas.isHardwareAccelerated()) {
drawHardwareAccelerated(canvas, layout, highlightPaths, highlightPaints,
selectionHighlight, selectionHighlightPaint, cursorOffsetVertical);
@@ -8054,6 +8062,110 @@
}
}
+ private static final class InsertModeController {
+ private final TextView mTextView;
+ private boolean mIsInsertModeActive;
+ private InsertModeTransformationMethod mInsertModeTransformationMethod;
+ private final Paint mHighlightPaint;
+
+ InsertModeController(@NonNull TextView textView) {
+ mTextView = Objects.requireNonNull(textView);
+ mIsInsertModeActive = false;
+ mInsertModeTransformationMethod = null;
+ mHighlightPaint = new Paint();
+
+ // The highlight color is supposed to be 12% of the color primary40. We can't
+ // directly access Material 3 theme. But because Material 3 sets the colorPrimary to
+ // be primary40, here we hardcoded it to be 12% of colorPrimary.
+ final TypedValue typedValue = new TypedValue();
+ mTextView.getContext().getTheme()
+ .resolveAttribute(R.attr.colorPrimary, typedValue, true);
+ final int colorPrimary = typedValue.data;
+ final int highlightColor = ColorUtils.setAlphaComponent(colorPrimary,
+ (int) (0.12f * Color.alpha(colorPrimary)));
+ mHighlightPaint.setColor(highlightColor);
+ }
+
+ /**
+ * Enter insert mode.
+ * @param offset the index to set the cursor.
+ * @return true if the call is successful. false if a) it's already in the insert mode,
+ * b) it failed to enter the insert mode.
+ */
+ boolean enterInsertMode(int offset) {
+ if (mIsInsertModeActive) return false;
+
+ TransformationMethod oldTransformationMethod =
+ mTextView.getTransformationMethod();
+ if (oldTransformationMethod instanceof OffsetMapping) {
+ // We can't support the case where the oldTransformationMethod is an OffsetMapping.
+ return false;
+ }
+
+ final boolean isSingleLine = mTextView.isSingleLine();
+ mInsertModeTransformationMethod = new InsertModeTransformationMethod(offset,
+ isSingleLine, oldTransformationMethod);
+ mTextView.setTransformationMethod(mInsertModeTransformationMethod);
+ Selection.setSelection((Spannable) mTextView.getText(), offset);
+
+ mIsInsertModeActive = true;
+ return true;
+ }
+
+ void exitInsertMode() {
+ if (!mIsInsertModeActive) return;
+ if (mInsertModeTransformationMethod == null
+ || mInsertModeTransformationMethod != mTextView.getTransformationMethod()) {
+ // If mInsertionModeTransformationMethod doesn't match the one on TextView,
+ // something else have changed the TextView's TransformationMethod while the
+ // insertion mode is active. We don't need to restore the oldTransformationMethod.
+ // TODO(265871733): support the case where setTransformationMethod is called in
+ // the insert mode.
+ mIsInsertModeActive = false;
+ return;
+ }
+ // Changing TransformationMethod will reset selection range to [0, 0), we need to
+ // manually restore the old selection range.
+ final int selectionStart = mTextView.getSelectionStart();
+ final int selectionEnd = mTextView.getSelectionEnd();
+ final TransformationMethod oldTransformationMethod =
+ mInsertModeTransformationMethod.getOldTransformationMethod();
+ mTextView.setTransformationMethod(oldTransformationMethod);
+ Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd);
+ mIsInsertModeActive = false;
+ }
+
+ void onDraw(Canvas canvas) {
+ if (!mIsInsertModeActive) return;
+ final CharSequence transformedText = mTextView.getTransformed();
+ if (transformedText instanceof InsertModeTransformationMethod.TransformedText) {
+ final Layout layout = mTextView.getLayout();
+ if (layout == null) return;
+ final InsertModeTransformationMethod.TransformedText insertModeTransformedText =
+ ((InsertModeTransformationMethod.TransformedText) transformedText);
+ final int highlightStart = insertModeTransformedText.getHighlightStart();
+ final int highlightEnd = insertModeTransformedText.getHighlightEnd();
+ final Layout.SelectionRectangleConsumer consumer =
+ (left, top, right, bottom, textSelectionLayout) ->
+ canvas.drawRect(left, top, right, bottom, mHighlightPaint);
+ layout.getSelection(highlightStart, highlightEnd, consumer);
+ }
+ }
+ }
+
+ boolean enterInsertMode(int offset) {
+ if (mInsertModeController == null) {
+ if (mTextView == null) return false;
+ mInsertModeController = new InsertModeController(mTextView);
+ }
+ return mInsertModeController.enterInsertMode(offset);
+ }
+
+ void exitInsertMode() {
+ if (mInsertModeController == null) return;
+ mInsertModeController.exitInsertMode();
+ }
+
/**
* Initializes the nodeInfo with smart actions.
*/
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6ff808e..6e36a03 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -202,6 +202,7 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.InsertModeGesture;
import android.view.inputmethod.JoinOrSplitGesture;
import android.view.inputmethod.PreviewableHandwritingGesture;
import android.view.inputmethod.RemoveSpaceGesture;
@@ -2534,7 +2535,7 @@
/**
* @hide
*/
- @VisibleForTesting
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public CharSequence getTransformed() {
return mTransformed;
}
@@ -9620,6 +9621,7 @@
gestures.add(InsertGesture.class);
gestures.add(RemoveSpaceGesture.class);
gestures.add(JoinOrSplitGesture.class);
+ gestures.add(InsertModeGesture.class);
outAttrs.setSupportedHandwritingGestures(gestures);
Set<Class<? extends PreviewableHandwritingGesture>> previews = new ArraySet<>();
@@ -10169,6 +10171,27 @@
return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
}
+ /** @hide */
+ public int performHandwritingInsertModeGesture(@NonNull InsertModeGesture gesture) {
+ final PointF insertPoint =
+ convertFromScreenToContentCoordinates(gesture.getInsertionPoint());
+ final int line = getLineForHandwritingGesture(insertPoint);
+ final CancellationSignal cancellationSignal = gesture.getCancellationSignal();
+
+ // If no cancellationSignal is provided, don't enter the insert mode.
+ if (line == -1 || cancellationSignal == null) {
+ return handleGestureFailure(gesture);
+ }
+
+ final int offset = mLayout.getOffsetForHorizontal(line, insertPoint.x);
+
+ if (!mEditor.enterInsertMode(offset)) {
+ return InputConnection.HANDWRITING_GESTURE_RESULT_FAILED;
+ }
+ cancellationSignal.setOnCancelListener(() -> mEditor.exitInsertMode());
+ return InputConnection.HANDWRITING_GESTURE_RESULT_SUCCESS;
+ }
+
private int handleGestureFailure(HandwritingGesture gesture) {
return handleGestureFailure(gesture, /* isPreview= */ false);
}
diff --git a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
index bf55255..ef25501 100644
--- a/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
+++ b/core/java/com/android/internal/accessibility/AccessibilityShortcutController.java
@@ -438,9 +438,18 @@
? AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
: AudioAttributes.USAGE_NOTIFICATION_EVENT;
+ // Use the default accessibility notification sound instead to avoid users confusing the new
+ // notification received. Point to the default notification sound if the sound does not
+ // exist.
+ final Uri ringtoneUri = Uri.parse("file://"
+ + mContext.getString(R.string.config_defaultAccessibilityNotificationSound));
+ Ringtone tone = mFrameworkObjectProvider.getRingtone(mContext, ringtoneUri);
+ if (tone == null) {
+ tone = mFrameworkObjectProvider.getRingtone(mContext,
+ Settings.System.DEFAULT_NOTIFICATION_URI);
+ }
+
// Play a notification tone
- final Ringtone tone = mFrameworkObjectProvider.getRingtone(mContext,
- Settings.System.DEFAULT_NOTIFICATION_URI);
if (tone != null) {
tone.setAudioAttributes(new AudioAttributes.Builder()
.setUsage(audioAttributesUsage)
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index 2316738..5e2eceb 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -16,8 +16,8 @@
package com.android.internal.app;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.content.ContentResolver;
@@ -60,16 +60,19 @@
private Set<Integer> mLoadedPages;
private final EmptyStateProvider mEmptyStateProvider;
private final UserHandle mWorkProfileUserHandle;
+ private final UserHandle mCloneUserHandle;
private final QuietModeManager mQuietModeManager;
AbstractMultiProfilePagerAdapter(Context context, int currentPage,
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
- UserHandle workProfileUserHandle) {
+ UserHandle workProfileUserHandle,
+ UserHandle cloneUserHandle) {
mContext = Objects.requireNonNull(context);
mCurrentPage = currentPage;
mLoadedPages = new HashSet<>();
mWorkProfileUserHandle = workProfileUserHandle;
+ mCloneUserHandle = cloneUserHandle;
mEmptyStateProvider = emptyStateProvider;
mQuietModeManager = quietModeManager;
}
@@ -160,6 +163,10 @@
return null;
}
+ public UserHandle getCloneUserHandle() {
+ return mCloneUserHandle;
+ }
+
/**
* Returns the {@link ProfileDescriptor} relevant to the given <code>pageIndex</code>.
* <ul>
diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java
index 9759540..930f6e0 100644
--- a/core/java/com/android/internal/app/AbstractResolverComparator.java
+++ b/core/java/com/android/internal/app/AbstractResolverComparator.java
@@ -30,11 +30,16 @@
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+import com.android.internal.app.chooser.TargetInfo;
+
+import com.google.android.collect.Lists;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Used to sort resolved activities in {@link ResolverListController}.
@@ -48,8 +53,8 @@
private static final String TAG = "AbstractResolverComp";
protected AfterCompute mAfterCompute;
- protected final PackageManager mPm;
- protected final UsageStatsManager mUsm;
+ protected final Map<UserHandle, PackageManager> mPmMap = new HashMap<>();
+ protected final Map<UserHandle, UsageStatsManager> mUsmMap = new HashMap<>();
protected String[] mAnnotations;
protected String mContentType;
@@ -98,14 +103,28 @@
}
};
- public AbstractResolverComparator(Context context, Intent intent) {
+ // context here refers to the activity calling this comparator.
+ // targetUserSpace refers to the userSpace in which the targets to be ranked lie.
+ public AbstractResolverComparator(Context launchedFromContext, Intent intent,
+ UserHandle targetUserSpace) {
+ this(launchedFromContext, intent, Lists.newArrayList(targetUserSpace));
+ }
+
+ // context here refers to the activity calling this comparator.
+ // targetUserSpaceList refers to the userSpace(s) in which the targets to be ranked lie.
+ public AbstractResolverComparator(Context launchedFromContext, Intent intent,
+ List<UserHandle> targetUserSpaceList) {
String scheme = intent.getScheme();
mHttp = "http".equals(scheme) || "https".equals(scheme);
mContentType = intent.getType();
getContentAnnotations(intent);
- mPm = context.getPackageManager();
- mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
- mAzComparator = new AzInfoComparator(context);
+ for (UserHandle user : targetUserSpaceList) {
+ Context userContext = launchedFromContext.createContextAsUser(user, 0);
+ mPmMap.put(user, userContext.getPackageManager());
+ mUsmMap.put(user,
+ (UsageStatsManager) userContext.getSystemService(Context.USAGE_STATS_SERVICE));
+ }
+ mAzComparator = new AzInfoComparator(launchedFromContext);
}
// get annotations of content from intent.
@@ -208,8 +227,8 @@
/**
* Computes features for each target. This will be called before calls to {@link
- * #getScore(ComponentName)} or {@link #compare(Object, Object)}, in order to prepare the
- * comparator for those calls. Note that {@link #getScore(ComponentName)} uses {@link
+ * #getScore(TargetInfo)} or {@link #compare(ResolveInfo, ResolveInfo)}, in order to prepare the
+ * comparator for those calls. Note that {@link #getScore(TargetInfo)} uses {@link
* ComponentName}, so the implementation will have to be prepared to identify a {@link
* ResolvedComponentInfo} by {@link ComponentName}. {@link #beforeCompute()} will be called
* before doing any computing.
@@ -226,7 +245,7 @@
* Returns the score that was calculated for the corresponding {@link ResolvedComponentInfo}
* when {@link #compute(List)} was called before this.
*/
- abstract float getScore(ComponentName name);
+ abstract float getScore(TargetInfo targetInfo);
/** Handles result message sent to mHandler. */
abstract void handleResultMessage(Message message);
@@ -234,9 +253,11 @@
/**
* Reports to UsageStats what was chosen.
*/
- final void updateChooserCounts(String packageName, int userId, String action) {
- if (mUsm != null) {
- mUsm.reportChooserSelection(packageName, userId, mContentType, mAnnotations, action);
+ final void updateChooserCounts(String packageName, UserHandle user, String action) {
+ if (mUsmMap.containsKey(user)) {
+ mUsmMap.get(user)
+ .reportChooserSelection(packageName, user.getIdentifier(), mContentType,
+ mAnnotations, action);
}
}
@@ -246,9 +267,9 @@
* <p>Default implementation does nothing, as we could have simple model that does not train
* online.
*
- * @param componentName the component that the user clicked
+ * @param targetInfo the target that the user clicked.
*/
- void updateModel(ComponentName componentName) {
+ void updateModel(TargetInfo targetInfo) {
}
/** Called before {@link #doCompute(List)}. Sets up 500ms timeout. */
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index 115a9d7..b9f0236 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -31,6 +31,9 @@
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+import com.android.internal.app.chooser.TargetInfo;
+
+import com.google.android.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
@@ -70,7 +73,7 @@
AppPredictor appPredictor,
UserHandle user,
ChooserActivityLogger chooserActivityLogger) {
- super(context, intent);
+ super(context, intent, Lists.newArrayList(user));
mContext = context;
mIntent = intent;
mAppPredictor = appPredictor;
@@ -99,13 +102,13 @@
}
@Override
- float getScore(ComponentName name) {
- return mComparatorModel.getScore(name);
+ float getScore(TargetInfo targetInfo) {
+ return mComparatorModel.getScore(targetInfo);
}
@Override
- void updateModel(ComponentName componentName) {
- mComparatorModel.notifyOnTargetSelected(componentName);
+ void updateModel(TargetInfo targetInfo) {
+ mComparatorModel.notifyOnTargetSelected(targetInfo);
}
@Override
@@ -158,9 +161,12 @@
private void setupFallbackModel(List<ResolvedComponentInfo> targets) {
mResolverRankerService =
new ResolverRankerServiceResolverComparator(
- mContext, mIntent, mReferrerPackage,
+ mContext,
+ mIntent,
+ mReferrerPackage,
() -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT),
- getChooserActivityLogger());
+ getChooserActivityLogger(),
+ mUser);
mComparatorModel = mModelBuilder.buildFallbackModel(mResolverRankerService);
mResolverRankerService.compute(targets);
}
@@ -224,13 +230,13 @@
}
@Override
- public float getScore(ComponentName componentName) {
- return comparator.getScore(componentName);
+ public float getScore(TargetInfo targetInfo) {
+ return comparator.getScore(targetInfo);
}
@Override
- public void notifyOnTargetSelected(ComponentName componentName) {
- comparator.updateModel(componentName);
+ public void notifyOnTargetSelected(TargetInfo targetInfo) {
+ comparator.updateModel(targetInfo);
}
};
}
@@ -271,8 +277,8 @@
}
@Override
- public float getScore(ComponentName name) {
- Integer rank = mTargetRanks.get(name);
+ public float getScore(TargetInfo targetInfo) {
+ Integer rank = mTargetRanks.get(targetInfo.getResolvedComponentName());
if (rank == null) {
Log.w(TAG, "Score requested for unknown component. Did you call compute yet?");
return 0f;
@@ -282,13 +288,14 @@
}
@Override
- public void notifyOnTargetSelected(ComponentName componentName) {
+ public void notifyOnTargetSelected(TargetInfo targetInfo) {
mAppPredictor.notifyAppTargetEvent(
new AppTargetEvent.Builder(
new AppTarget.Builder(
- new AppTargetId(componentName.toString()),
- componentName.getPackageName(), mUser)
- .setClassName(componentName.getClassName()).build(),
+ new AppTargetId(targetInfo.getResolvedComponentName().toString()),
+ targetInfo.getResolvedComponentName().getPackageName(), mUser)
+ .setClassName(targetInfo.getResolvedComponentName()
+ .getClassName()).build(),
ACTION_LAUNCH).build());
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 9f283d4..f257f1c 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -873,7 +873,7 @@
return new NoCrossProfileEmptyStateProvider(getPersonalProfileUserHandle(),
noWorkToPersonalEmptyState, noPersonalToWorkEmptyState,
- createCrossProfileIntentsChecker(), createMyUserIdProvider());
+ createCrossProfileIntentsChecker(), getTabOwnerUserHandleForLaunch());
}
private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForOneProfile(
@@ -886,13 +886,14 @@
initialIntents,
rList,
filterLastUsed,
- /* userHandle */ UserHandle.of(UserHandle.myUserId()));
+ /* userHandle */ getPersonalProfileUserHandle());
return new ChooserMultiProfilePagerAdapter(
/* context */ this,
adapter,
createEmptyStateProvider(/* workProfileUserHandle= */ null),
mQuietModeManager,
/* workProfileUserHandle= */ null,
+ getCloneProfileUserHandle(),
mMaxTargetsPerRow);
}
@@ -923,13 +924,14 @@
mQuietModeManager,
selectedProfile,
getWorkProfileUserHandle(),
+ getCloneProfileUserHandle(),
mMaxTargetsPerRow);
}
private int findSelectedProfile() {
int selectedProfile = getSelectedProfileExtra();
if (selectedProfile == -1) {
- selectedProfile = getProfileForUser(getUser());
+ selectedProfile = getProfileForUser(getTabOwnerUserHandleForLaunch());
}
return selectedProfile;
}
@@ -1800,8 +1802,12 @@
targetList = new ArrayList<DisplayResolveInfo>();
targetList.add((DisplayResolveInfo) targetInfo);
}
+ // Adding userHandle from ResolveInfo allows the app icon in Dialog Box to be
+ // resolved correctly.
bundle.putParcelable(ChooserTargetActionsDialogFragment.USER_HANDLE_KEY,
- mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
+ getResolveInfoUserHandle(
+ targetInfo.getResolveInfo(),
+ mChooserMultiProfilePagerAdapter.getCurrentUserHandle()));
bundle.putParcelableArrayList(ChooserTargetActionsDialogFragment.TARGET_INFOS_KEY,
targetList);
fragment.setArguments(bundle);
@@ -1865,8 +1871,11 @@
if (!mti.hasSelected()) {
ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment();
Bundle b = new Bundle();
+ // Add userHandle based badge to the stackedAppDialogBox.
b.putParcelable(ChooserTargetActionsDialogFragment.USER_HANDLE_KEY,
- mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
+ getResolveInfoUserHandle(
+ targetInfo.getResolveInfo(),
+ mChooserMultiProfilePagerAdapter.getCurrentUserHandle()));
b.putObject(ChooserStackedAppDialogFragment.MULTI_DRI_KEY,
mti);
b.putInt(ChooserStackedAppDialogFragment.WHICH_KEY, which);
@@ -2259,9 +2268,11 @@
mChooserMultiProfilePagerAdapter.getActiveListAdapter();
if (currentListAdapter != null) {
sendImpressionToAppPredictor(info, currentListAdapter);
- currentListAdapter.updateModel(info.getResolvedComponentName());
- currentListAdapter.updateChooserCounts(ri.activityInfo.packageName,
- targetIntent.getAction());
+ currentListAdapter.updateModel(info);
+ currentListAdapter.updateChooserCounts(
+ ri.activityInfo.packageName,
+ targetIntent.getAction(),
+ ri.userHandle);
}
if (DEBUG) {
Log.d(TAG, "ResolveInfo Package is " + ri.activityInfo.packageName);
@@ -2386,7 +2397,10 @@
*/
@Nullable
private AppPredictor getAppPredictorForShareActivitiesIfEnabled(UserHandle userHandle) {
- return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? createAppPredictor(userHandle) : null;
+ // We cannot use APS service when clone profile is present as APS service cannot sort
+ // cross profile targets as of now.
+ return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES && getCloneProfileUserHandle() == null
+ ? createAppPredictor(userHandle) : null;
}
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
@@ -2433,15 +2447,24 @@
* Sort intents alphabetically based on display label.
*/
static class AzInfoComparator implements Comparator<DisplayResolveInfo> {
- Collator mCollator;
+ Comparator<DisplayResolveInfo> mComparator;
AzInfoComparator(Context context) {
- mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
+ Collator collator = Collator
+ .getInstance(context.getResources().getConfiguration().locale);
+ // Adding two stage comparator, first stage compares using displayLabel, next stage
+ // compares using resolveInfo.userHandle
+ mComparator = Comparator.comparing(DisplayResolveInfo::getDisplayLabel, collator)
+ .thenComparingInt(displayResolveInfo ->
+ getResolveInfoUserHandle(
+ displayResolveInfo.getResolveInfo(),
+ // TODO: User resolveInfo.userHandle, once its available.
+ UserHandle.SYSTEM).getIdentifier());
}
@Override
public int compare(
DisplayResolveInfo lhsp, DisplayResolveInfo rhsp) {
- return mCollator.compare(lhsp.getDisplayLabel(), rhsp.getDisplayLabel());
+ return mComparator.compare(lhsp, rhsp);
}
}
@@ -2466,9 +2489,10 @@
String referrerPackageName,
int launchedFromUid,
UserHandle userId,
- AbstractResolverComparator resolverComparator) {
+ AbstractResolverComparator resolverComparator,
+ UserHandle queryIntentsAsUser) {
super(context, pm, targetIntent, referrerPackageName, launchedFromUid, userId,
- resolverComparator);
+ resolverComparator, queryIntentsAsUser);
}
@Override
@@ -2529,10 +2553,16 @@
getReferrerPackageName(), appPredictor, userHandle, getChooserActivityLogger());
} else {
resolverComparator =
- new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
- getReferrerPackageName(), null, getChooserActivityLogger());
+ new ResolverRankerServiceResolverComparator(
+ this,
+ getTargetIntent(),
+ getReferrerPackageName(),
+ null,
+ getChooserActivityLogger(),
+ getResolverRankerServiceUserHandleList(userHandle));
}
+ UserHandle queryIntentsUser = getQueryIntentsUser(userHandle);
return new ChooserListController(
this,
mPm,
@@ -2540,7 +2570,8 @@
getReferrerPackageName(),
mLaunchedFromUid,
userHandle,
- resolverComparator);
+ resolverComparator,
+ queryIntentsUser == null ? userHandle : queryIntentsUser);
}
@VisibleForTesting
@@ -2741,17 +2772,16 @@
}
/**
- * Returns {@link #PROFILE_PERSONAL}, {@link #PROFILE_WORK}, or -1 if the given user handle
- * does not match either the personal or work user handle.
+ * Returns {@link #PROFILE_WORK}, if the given user handle matches work user handle.
+ * Returns {@link #PROFILE_PERSONAL}, otherwise.
**/
private int getProfileForUser(UserHandle currentUserHandle) {
- if (currentUserHandle.equals(getPersonalProfileUserHandle())) {
- return PROFILE_PERSONAL;
- } else if (currentUserHandle.equals(getWorkProfileUserHandle())) {
+ if (currentUserHandle.equals(getWorkProfileUserHandle())) {
return PROFILE_WORK;
}
- Log.e(TAG, "User " + currentUserHandle + " does not belong to a personal or work profile.");
- return -1;
+ // We return personal profile, as it is the default when there is no work profile, personal
+ // profile represents rootUser, clonedUser & secondaryUser, covering all use cases.
+ return PROFILE_PERSONAL;
}
private ViewGroup getActiveEmptyStateView() {
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 2ae2c09..e0568cf 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -197,6 +197,7 @@
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
+ ri.userHandle = getUserHandle();
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
@@ -351,7 +352,9 @@
Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
for (DisplayResolveInfo info : allTargets) {
String resolvedTarget = info.getResolvedComponentName().getPackageName()
- + '#' + info.getDisplayLabel();
+ + '#' + info.getDisplayLabel()
+ + '#' + ResolverActivity.getResolveInfoUserHandle(
+ info.getResolveInfo(), getUserHandle()).getIdentifier();
DisplayResolveInfo multiDri = consolidated.get(resolvedTarget);
if (multiDri == null) {
consolidated.put(resolvedTarget, info);
@@ -367,7 +370,8 @@
}
List<DisplayResolveInfo> groupedTargets = new ArrayList<>();
groupedTargets.addAll(consolidated.values());
- Collections.sort(groupedTargets, new ChooserActivity.AzInfoComparator(mContext));
+ Collections.sort(groupedTargets,
+ new ChooserActivity.AzInfoComparator(mContext));
return groupedTargets;
}
@Override
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index 0509b67..f56f818 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -45,9 +45,10 @@
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
UserHandle workProfileUserHandle,
+ UserHandle cloneUserHandle,
int maxTargetsPerRow) {
super(context, /* currentPage */ 0, emptyStateProvider, quietModeManager,
- workProfileUserHandle);
+ workProfileUserHandle, cloneUserHandle);
mItems = new ChooserProfileDescriptor[] {
createProfileDescriptor(adapter)
};
@@ -61,9 +62,10 @@
QuietModeManager quietModeManager,
@Profile int defaultProfile,
UserHandle workProfileUserHandle,
+ UserHandle cloneUserHandle,
int maxTargetsPerRow) {
super(context, /* currentPage */ defaultProfile, emptyStateProvider,
- quietModeManager, workProfileUserHandle);
+ quietModeManager, workProfileUserHandle, cloneUserHandle);
mItems = new ChooserProfileDescriptor[] {
createProfileDescriptor(personalAdapter),
createProfileDescriptor(workAdapter)
@@ -110,11 +112,12 @@
@Override
@Nullable
ChooserListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
- if (getActiveListAdapter().getUserHandle().equals(userHandle)) {
- return getActiveListAdapter();
- } else if (getInactiveListAdapter() != null
- && getInactiveListAdapter().getUserHandle().equals(userHandle)) {
- return getInactiveListAdapter();
+ if (getPersonalListAdapter().getUserHandle().equals(userHandle)
+ || userHandle.equals(getCloneUserHandle())) {
+ return getPersonalListAdapter();
+ } else if (getWorkListAdapter() != null
+ && getWorkListAdapter().getUserHandle().equals(userHandle)) {
+ return getWorkListAdapter();
}
return null;
}
@@ -153,13 +156,13 @@
}
@Override
- public ResolverListAdapter getPersonalListAdapter() {
+ public ChooserListAdapter getPersonalListAdapter() {
return getAdapterForIndex(PROFILE_PERSONAL).getListAdapter();
}
@Override
@Nullable
- public ResolverListAdapter getWorkListAdapter() {
+ public ChooserListAdapter getWorkListAdapter() {
return getAdapterForIndex(PROFILE_WORK).getListAdapter();
}
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 3efd279..3619c7b 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -21,6 +21,7 @@
import android.app.ListFragment;
import android.content.Context;
import android.os.Bundle;
+import android.os.LocaleList;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
@@ -102,15 +103,21 @@
public static LocalePickerWithRegion createLanguagePicker(Context context,
LocaleSelectedListener listener, boolean translatedOnly) {
- return createLanguagePicker(context, listener, translatedOnly, null, null);
+ return createLanguagePicker(context, listener, translatedOnly, null, null, null);
}
public static LocalePickerWithRegion createLanguagePicker(Context context,
- LocaleSelectedListener listener, boolean translatedOnly, String appPackageName,
- OnActionExpandListener onActionExpandListener) {
+ LocaleSelectedListener listener, boolean translatedOnly, LocaleList explicitLocales) {
+ return createLanguagePicker(context, listener, translatedOnly, explicitLocales, null, null);
+ }
+
+ /** Creates language picker UI */
+ public static LocalePickerWithRegion createLanguagePicker(Context context,
+ LocaleSelectedListener listener, boolean translatedOnly, LocaleList explicitLocales,
+ String appPackageName, OnActionExpandListener onActionExpandListener) {
LocaleCollectorBase localePickerController;
if (TextUtils.isEmpty(appPackageName)) {
- localePickerController = new SystemLocaleCollector(context);
+ localePickerController = new SystemLocaleCollector(context, explicitLocales);
} else {
localePickerController = new AppLocaleCollector(context, appPackageName);
}
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index d2eee91..bcff907 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -22,6 +22,7 @@
import android.os.LocaleList;
import android.provider.Settings;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.InputMethodSubtype;
@@ -29,6 +30,7 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IllformedLocaleException;
@@ -106,6 +108,9 @@
return mParent;
}
+ /**
+ * TODO: This method may rename to be more generic i.e. toLanguageTag().
+ */
@UnsupportedAppUsage
public String getId() {
return mId;
@@ -456,11 +461,30 @@
@UnsupportedAppUsage
public static Set<LocaleInfo> getLevelLocales(Context context, Set<String> ignorables,
LocaleInfo parent, boolean translatedOnly) {
+ return getLevelLocales(context, ignorables, parent, translatedOnly, null);
+ }
+
+ /**
+ * @param explicitLocales Indicates only the locales within this list should be shown in the
+ * locale picker.
+ *
+ * Returns a list of locales for language or region selection.
+ * If the parent is null, then it is the language list.
+ * If it is not null, then the list will contain all the locales that belong to that parent.
+ * Example: if the parent is "ar", then the region list will contain all Arabic locales.
+ * (this is not language based, but language-script, so that it works for zh-Hant and so on.
+ */
+ public static Set<LocaleInfo> getLevelLocales(Context context, Set<String> ignorables,
+ LocaleInfo parent, boolean translatedOnly, LocaleList explicitLocales) {
fillCache(context);
String parentId = parent == null ? null : parent.getId();
-
HashSet<LocaleInfo> result = new HashSet<>();
- for (LocaleStore.LocaleInfo li : sLocaleCache.values()) {
+ HashMap<String, LocaleInfo> supportedLcoaleInfos =
+ explicitLocales == null
+ ? sLocaleCache
+ : convertExplicitLocales(explicitLocales, sLocaleCache.values());
+
+ for (LocaleStore.LocaleInfo li : supportedLcoaleInfos.values()) {
int level = getLevel(ignorables, li, translatedOnly);
if (level == 2) {
if (parent != null) { // region selection
@@ -479,6 +503,61 @@
return result;
}
+ /** Converts string array of explicit locales to HashMap */
+ public static HashMap<String, LocaleInfo> convertExplicitLocales(
+ LocaleList explicitLocales, Collection<LocaleInfo> localeinfo) {
+ // Trys to find the matched locale within android supported locales. If there is no matched
+ // locale, it will still keep the unsupported lcoale in list.
+ // Note: This currently does not support unicode extension check.
+ LocaleList localeList = matchLocaleFromSupportedLocaleList(
+ explicitLocales, localeinfo);
+
+ HashMap<String, LocaleInfo> localeInfos = new HashMap<>();
+ for (int i = 0; i < localeList.size(); i++) {
+ Locale locale = localeList.get(i);
+ if (locale.toString().isEmpty()) {
+ throw new IllformedLocaleException("Bad locale entry");
+ }
+
+ LocaleInfo li = new LocaleInfo(locale);
+ if (localeInfos.containsKey(li.getId())) {
+ continue;
+ }
+ localeInfos.put(li.getId(), li);
+ Locale parent = li.getParent();
+ if (parent != null) {
+ String parentId = parent.toLanguageTag();
+ if (!localeInfos.containsKey(parentId)) {
+ localeInfos.put(parentId, new LocaleInfo(parent));
+ }
+ }
+ }
+ return localeInfos;
+ }
+
+ private static LocaleList matchLocaleFromSupportedLocaleList(
+ LocaleList explicitLocales, Collection<LocaleInfo> localeinfo) {
+ //TODO: Adds a function for unicode extension if needed.
+ Locale[] resultLocales = new Locale[explicitLocales.size()];
+ for (int i = 0; i < explicitLocales.size(); i++) {
+ Locale locale = explicitLocales.get(i).stripExtensions();
+ if (!TextUtils.isEmpty(locale.getCountry())) {
+ for (LocaleInfo localeInfo :localeinfo) {
+ if (LocaleList.matchesLanguageAndScript(locale, localeInfo.getLocale())
+ && TextUtils.equals(locale.getCountry(),
+ localeInfo.getLocale().getCountry())) {
+ resultLocales[i] = localeInfo.getLocale();
+ continue;
+ }
+ }
+ }
+ if (resultLocales[i] == null) {
+ resultLocales[i] = locale;
+ }
+ }
+ return new LocaleList(resultLocales);
+ }
+
@UnsupportedAppUsage
public static LocaleInfo getLocaleInfo(Locale locale) {
String id = locale.toLanguageTag();
diff --git a/core/java/com/android/internal/app/NoAppsAvailableEmptyStateProvider.java b/core/java/com/android/internal/app/NoAppsAvailableEmptyStateProvider.java
index 34249f2..747780b 100644
--- a/core/java/com/android/internal/app/NoAppsAvailableEmptyStateProvider.java
+++ b/core/java/com/android/internal/app/NoAppsAvailableEmptyStateProvider.java
@@ -28,10 +28,9 @@
import android.os.UserHandle;
import android.stats.devicepolicy.nano.DevicePolicyEnums;
+import com.android.internal.R;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider;
-import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
-import com.android.internal.R;
import java.util.List;
@@ -50,16 +49,16 @@
@NonNull
private final String mMetricsCategory;
@NonNull
- private final MyUserIdProvider mMyUserIdProvider;
+ private final UserHandle mTabOwnerUserHandleForLaunch;
public NoAppsAvailableEmptyStateProvider(Context context, UserHandle workProfileUserHandle,
UserHandle personalProfileUserHandle, String metricsCategory,
- MyUserIdProvider myUserIdProvider) {
+ UserHandle tabOwnerUserHandleForLaunch) {
mContext = context;
mWorkProfileUserHandle = workProfileUserHandle;
mPersonalProfileUserHandle = personalProfileUserHandle;
mMetricsCategory = metricsCategory;
- mMyUserIdProvider = myUserIdProvider;
+ mTabOwnerUserHandleForLaunch = tabOwnerUserHandleForLaunch;
}
@Nullable
@@ -69,7 +68,7 @@
UserHandle listUserHandle = resolverListAdapter.getUserHandle();
if (mWorkProfileUserHandle != null
- && (mMyUserIdProvider.getMyUserId() == listUserHandle.getIdentifier()
+ && (mTabOwnerUserHandleForLaunch.equals(listUserHandle)
|| !hasAppsInOtherProfile(resolverListAdapter))) {
String title;
@@ -102,7 +101,7 @@
return false;
}
List<ResolverActivity.ResolvedComponentInfo> resolversForIntent =
- adapter.getResolversForUser(UserHandle.of(mMyUserIdProvider.getMyUserId()));
+ adapter.getResolversForUser(mTabOwnerUserHandleForLaunch);
for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) {
ResolveInfo resolveInfo = info.getResolveInfoAt(0);
if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) {
diff --git a/core/java/com/android/internal/app/NoCrossProfileEmptyStateProvider.java b/core/java/com/android/internal/app/NoCrossProfileEmptyStateProvider.java
index 2e7d5bf..2046bfc 100644
--- a/core/java/com/android/internal/app/NoCrossProfileEmptyStateProvider.java
+++ b/core/java/com/android/internal/app/NoCrossProfileEmptyStateProvider.java
@@ -27,7 +27,6 @@
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider;
-import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
/**
* Empty state provider that does not allow cross profile sharing, it will return a blocker
@@ -39,28 +38,28 @@
private final EmptyState mNoWorkToPersonalEmptyState;
private final EmptyState mNoPersonalToWorkEmptyState;
private final CrossProfileIntentsChecker mCrossProfileIntentsChecker;
- private final MyUserIdProvider mUserIdProvider;
+ private final UserHandle mTabOwnerUserHandleForLaunch;
public NoCrossProfileEmptyStateProvider(UserHandle personalUserHandle,
EmptyState noWorkToPersonalEmptyState,
EmptyState noPersonalToWorkEmptyState,
CrossProfileIntentsChecker crossProfileIntentsChecker,
- MyUserIdProvider myUserIdProvider) {
+ UserHandle preselectedTabOwnerUserHandle) {
mPersonalProfileUserHandle = personalUserHandle;
mNoWorkToPersonalEmptyState = noWorkToPersonalEmptyState;
mNoPersonalToWorkEmptyState = noPersonalToWorkEmptyState;
mCrossProfileIntentsChecker = crossProfileIntentsChecker;
- mUserIdProvider = myUserIdProvider;
+ mTabOwnerUserHandleForLaunch = preselectedTabOwnerUserHandle;
}
@Nullable
@Override
public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) {
boolean shouldShowBlocker =
- mUserIdProvider.getMyUserId() != resolverListAdapter.getUserHandle().getIdentifier()
+ !mTabOwnerUserHandleForLaunch.equals(resolverListAdapter.getUserHandle())
&& !mCrossProfileIntentsChecker
.hasCrossProfileIntents(resolverListAdapter.getIntents(),
- mUserIdProvider.getMyUserId(),
+ mTabOwnerUserHandleForLaunch.getIdentifier(),
resolverListAdapter.getUserHandle().getIdentifier());
if (!shouldShowBlocker) {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index f098e2c..992e243 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -166,6 +166,7 @@
@UnsupportedAppUsage
protected PackageManager mPm;
protected int mLaunchedFromUid;
+ private UserHandle mLaunchedFromUserHandle;
private static final String TAG = "ResolverActivity";
private static final boolean DEBUG = false;
@@ -229,12 +230,15 @@
private BroadcastReceiver mWorkProfileStateReceiver;
private UserHandle mHeaderCreatorUser;
-
+ private UserHandle mPersonalProfileUserHandle;
private UserHandle mWorkProfileUserHandle;
@Nullable
private OnSwitchOnWorkSelectedListener mOnSwitchOnWorkSelectedListener;
+ private UserHandle mCloneProfileUserHandle;
+ private UserHandle mTabOwnerUserHandleForLaunch;
+
protected final LatencyTracker mLatencyTracker = getLatencyTracker();
private LatencyTracker getLatencyTracker() {
@@ -400,6 +404,7 @@
setProfileSwitchMessage(intent.getContentUserHint());
mLaunchedFromUid = getLaunchedFromUid();
+ mLaunchedFromUserHandle = UserHandle.getUserHandleForUid(mLaunchedFromUid);
if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
// Gulp!
finish();
@@ -416,15 +421,21 @@
mDefaultTitleResId = defaultTitleRes;
mSupportsAlwaysUseOption = supportsAlwaysUseOption;
+ mPersonalProfileUserHandle = fetchPersonalProfileUserHandle();
mWorkProfileUserHandle = fetchWorkProfileUserProfile();
+ mCloneProfileUserHandle = fetchCloneProfileUserHandle();
+ mTabOwnerUserHandleForLaunch = fetchTabOwnerUserHandleForLaunch();
// The last argument of createResolverListAdapter is whether to do special handling
// of the last used choice to highlight it in the list. We need to always
// turn this off when running under voice interaction, since it results in
// a more complicated UI that the current voice interaction flow is not able
// to handle. We also turn it off when the work tab is shown to simplify the UX.
+ // We also turn it off when clonedProfile is present on the device, because we might have
+ // different "last chosen" activities in the different profiles, and PackageManager doesn't
+ // provide any more information to help us select between them.
boolean filterLastUsed = mSupportsAlwaysUseOption && !isVoiceInteraction()
- && !shouldShowTabs();
+ && !shouldShowTabs() && !hasCloneProfile();
mMultiProfilePagerAdapter = createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
if (configureContentView()) {
return;
@@ -566,9 +577,12 @@
/* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK,
/* devicePolicyEventCategory= */ ResolverActivity.METRICS_CATEGORY_RESOLVER);
- return new NoCrossProfileEmptyStateProvider(getPersonalProfileUserHandle(),
- noWorkToPersonalEmptyState, noPersonalToWorkEmptyState,
- createCrossProfileIntentsChecker(), createMyUserIdProvider());
+ return new NoCrossProfileEmptyStateProvider(
+ getPersonalProfileUserHandle(),
+ noWorkToPersonalEmptyState,
+ noPersonalToWorkEmptyState,
+ createCrossProfileIntentsChecker(),
+ getTabOwnerUserHandleForLaunch());
}
protected EmptyStateProvider createEmptyStateProvider(
@@ -589,7 +603,7 @@
workProfileUserHandle,
getPersonalProfileUserHandle(),
getMetricsCategory(),
- createMyUserIdProvider()
+ getTabOwnerUserHandleForLaunch()
);
// Return composite provider, the order matters (the higher, the more priority)
@@ -609,14 +623,15 @@
initialIntents,
rList,
filterLastUsed,
- /* userHandle */ UserHandle.of(UserHandle.myUserId()));
+ /* userHandle */ getPersonalProfileUserHandle());
QuietModeManager quietModeManager = createQuietModeManager();
return new ResolverMultiProfilePagerAdapter(
/* context */ this,
adapter,
createEmptyStateProvider(/* workProfileUserHandle= */ null),
quietModeManager,
- /* workProfileUserHandle= */ null);
+ /* workProfileUserHandle= */ null,
+ getCloneProfileUserHandle());
}
private UserHandle getIntentUser() {
@@ -634,7 +649,7 @@
// this happens, we check for it here and set the current profile's tab.
int selectedProfile = getCurrentProfile();
UserHandle intentUser = getIntentUser();
- if (!getUser().equals(intentUser)) {
+ if (!getTabOwnerUserHandleForLaunch().equals(intentUser)) {
if (getPersonalProfileUserHandle().equals(intentUser)) {
selectedProfile = PROFILE_PERSONAL;
} else if (getWorkProfileUserHandle().equals(intentUser)) {
@@ -674,7 +689,8 @@
createEmptyStateProvider(getWorkProfileUserHandle()),
quietModeManager,
selectedProfile,
- getWorkProfileUserHandle());
+ getWorkProfileUserHandle(),
+ getCloneProfileUserHandle());
}
protected int appliedThemeResId() {
@@ -701,20 +717,35 @@
}
protected @Profile int getCurrentProfile() {
- return (UserHandle.myUserId() == UserHandle.USER_SYSTEM ? PROFILE_PERSONAL : PROFILE_WORK);
+ return (UserHandle.myUserId() == getPersonalProfileUserHandle().getIdentifier()
+ ? PROFILE_PERSONAL : PROFILE_WORK);
}
protected UserHandle getPersonalProfileUserHandle() {
- return UserHandle.of(ActivityManager.getCurrentUser());
+ return mPersonalProfileUserHandle;
}
protected @Nullable UserHandle getWorkProfileUserHandle() {
return mWorkProfileUserHandle;
}
+ protected @Nullable UserHandle getCloneProfileUserHandle() {
+ return mCloneProfileUserHandle;
+ }
+
+ protected UserHandle getTabOwnerUserHandleForLaunch() {
+ return mTabOwnerUserHandleForLaunch;
+ }
+
+ protected UserHandle fetchPersonalProfileUserHandle() {
+ mPersonalProfileUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
+ return mPersonalProfileUserHandle;
+ }
+
protected @Nullable UserHandle fetchWorkProfileUserProfile() {
mWorkProfileUserHandle = null;
UserManager userManager = getSystemService(UserManager.class);
- for (final UserInfo userInfo : userManager.getProfiles(ActivityManager.getCurrentUser())) {
+ for (final UserInfo userInfo : userManager
+ .getProfiles(mPersonalProfileUserHandle.getIdentifier())) {
if (userInfo.isManagedProfile()) {
mWorkProfileUserHandle = userInfo.getUserHandle();
}
@@ -722,10 +753,38 @@
return mWorkProfileUserHandle;
}
+ protected @Nullable UserHandle fetchCloneProfileUserHandle() {
+ mCloneProfileUserHandle = null;
+ UserManager userManager = getSystemService(UserManager.class);
+ for (final UserInfo userInfo :
+ userManager.getProfiles(mPersonalProfileUserHandle.getIdentifier())) {
+ if (userInfo.isCloneProfile()) {
+ mCloneProfileUserHandle = userInfo.getUserHandle();
+ }
+ }
+ return mCloneProfileUserHandle;
+ }
+
+ private UserHandle fetchTabOwnerUserHandleForLaunch() {
+ if (isLaunchedAsCloneProfile()) {
+ return getPersonalProfileUserHandle();
+ }
+ return mLaunchedFromUserHandle;
+ }
+
private boolean hasWorkProfile() {
return getWorkProfileUserHandle() != null;
}
+ private boolean hasCloneProfile() {
+ return getCloneProfileUserHandle() != null;
+ }
+
+ private boolean isLaunchedAsCloneProfile() {
+ return hasCloneProfile()
+ && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier());
+ }
+
protected boolean shouldShowTabs() {
return hasWorkProfile() && ENABLE_TABBED_VIEW;
}
@@ -1123,6 +1182,14 @@
mAlwaysButton.setEnabled(false);
return;
}
+ // In case of clonedProfile being active, we do not allow the 'Always' option in the
+ // disambiguation dialog of Personal Profile as the package manager cannot distinguish
+ // between cross-profile preferred activities.
+ if (hasCloneProfile() && !mMultiProfilePagerAdapter
+ .getCurrentUserHandle().equals(mWorkProfileUserHandle)) {
+ mAlwaysButton.setEnabled(false);
+ return;
+ }
boolean enabled = false;
ResolveInfo ri = null;
if (hasValidSelection) {
@@ -1431,17 +1498,14 @@
return true;
}
- @VisibleForTesting
- public void safelyStartActivity(TargetInfo cti) {
- // We're dispatching intents that might be coming from legacy apps, so
- // don't kill ourselves.
- StrictMode.disableDeathOnFileUriExposure();
- try {
- UserHandle currentUserHandle = mMultiProfilePagerAdapter.getCurrentUserHandle();
- safelyStartActivityInternal(cti, currentUserHandle, null);
- } finally {
- StrictMode.enableDeathOnFileUriExposure();
- }
+ /** Start the activity specified by the {@link TargetInfo}.*/
+ public final void safelyStartActivity(TargetInfo cti) {
+ // In case cloned apps are present, we would want to start those apps in cloned user
+ // space, which will not be same as adaptor's userHandle. resolveInfo.userHandle
+ // identifies the correct user space in such cases.
+ UserHandle activityUserHandle = getResolveInfoUserHandle(
+ cti.getResolveInfo(), mMultiProfilePagerAdapter.getCurrentUserHandle());
+ safelyStartActivityAsUser(cti, activityUserHandle, null);
}
/**
@@ -1449,11 +1513,12 @@
* @param cti TargetInfo to be launched.
* @param user User to launch this activity as.
*/
- @VisibleForTesting
- public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user) {
+ public final void safelyStartActivityAsUser(TargetInfo cti, UserHandle user) {
safelyStartActivityAsUser(cti, user, null);
}
+ // TODO: Make method public final.
+ @VisibleForTesting
protected void safelyStartActivityAsUser(
TargetInfo cti, UserHandle user, @Nullable Bundle options) {
// We're dispatching intents that might be coming from legacy apps, so
@@ -1466,7 +1531,8 @@
}
}
- private void safelyStartActivityInternal(
+ @VisibleForTesting
+ protected void safelyStartActivityInternal(
TargetInfo cti, UserHandle user, @Nullable Bundle options) {
// If the target is suspended, the activity will not be successfully launched.
// Do not unregister from package manager updates in this case
@@ -1550,13 +1616,24 @@
@VisibleForTesting
protected ResolverListController createListController(UserHandle userHandle) {
+ UserHandle queryIntentsUser = getQueryIntentsUser(userHandle);
+ ResolverRankerServiceResolverComparator resolverComparator =
+ new ResolverRankerServiceResolverComparator(
+ this,
+ getTargetIntent(),
+ getReferrerPackageName(),
+ null,
+ null,
+ getResolverRankerServiceUserHandleList(userHandle));
return new ResolverListController(
this,
mPm,
getTargetIntent(),
getReferrerPackageName(),
mLaunchedFromUid,
- userHandle);
+ userHandle,
+ resolverComparator,
+ queryIntentsUser);
}
/**
@@ -2170,16 +2247,10 @@
public boolean useLayoutWithDefault() {
// We only use the default app layout when the profile of the active user has a
// filtered item. We always show the same default app even in the inactive user profile.
- boolean currentUserAdapterHasFilteredItem;
- if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
- == UserHandle.myUserId()) {
- currentUserAdapterHasFilteredItem =
- mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
- } else {
- currentUserAdapterHasFilteredItem =
- mMultiProfilePagerAdapter.getInactiveListAdapter().hasFilteredItem();
- }
- return mSupportsAlwaysUseOption && currentUserAdapterHasFilteredItem;
+ boolean adapterForCurrentUserHasFilteredItem =
+ mMultiProfilePagerAdapter.getListAdapterForUserHandle(
+ getTabOwnerUserHandleForLaunch()).hasFilteredItem();
+ return mSupportsAlwaysUseOption && adapterForCurrentUserHasFilteredItem;
}
/**
@@ -2198,7 +2269,14 @@
return lhs == null ? rhs == null
: lhs.activityInfo == null ? rhs.activityInfo == null
: Objects.equals(lhs.activityInfo.name, rhs.activityInfo.name)
- && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName);
+ && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName)
+ // Comparing against resolveInfo.userHandle in case cloned apps are present,
+ // as they will have the same activityInfo.
+ && Objects.equals(
+ getResolveInfoUserHandle(lhs,
+ mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()),
+ getResolveInfoUserHandle(rhs,
+ mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()));
}
protected String getMetricsCategory() {
@@ -2439,4 +2517,47 @@
}
protected void maybeLogProfileChange() {}
+
+ /**
+ * Returns the {@link UserHandle} to use when querying resolutions for intents in a
+ * {@link ResolverListController} configured for the provided {@code userHandle}.
+ */
+ protected final UserHandle getQueryIntentsUser(UserHandle userHandle) {
+ // In case launching app is in clonedProfile, and we are building the personal tab, intent
+ // resolution will be attempted as clonedUser instead of user 0. This is because intent
+ // resolution from user 0 and clonedUser is not guaranteed to return same results.
+ // We do not care about the case when personal adapter is started with non-root user
+ // (secondary user case), as clone profile is guaranteed to be non-active in that case.
+ UserHandle queryIntentsUser = userHandle;
+ if (isLaunchedAsCloneProfile() && userHandle.equals(getPersonalProfileUserHandle())) {
+ queryIntentsUser = getCloneProfileUserHandle();
+ }
+ return queryIntentsUser;
+ }
+
+ /**
+ * This function is temporary in nature, and its usages will be replaced with just
+ * resolveInfo.userHandle, once it is available, once sharesheet is stable.
+ */
+ public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
+ UserHandle predictedHandle) {
+ return resolveInfo.userHandle;
+ }
+
+ /**
+ * Returns the {@link List} of {@link UserHandle} to pass on to the
+ * {@link ResolverRankerServiceResolverComparator} as per the provided {@code userHandle}.
+ */
+ protected final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
+ List<UserHandle> userList = new ArrayList<>();
+ userList.add(userHandle);
+ // Add clonedProfileUserHandle to the list only if we are:
+ // a. Building the Personal Tab.
+ // b. CloneProfile exists on the device.
+ if (userHandle.equals(getPersonalProfileUserHandle())
+ && getCloneProfileUserHandle() != null) {
+ userList.add(getCloneProfileUserHandle());
+ }
+ return userList;
+ }
}
diff --git a/core/java/com/android/internal/app/ResolverComparatorModel.java b/core/java/com/android/internal/app/ResolverComparatorModel.java
index 3e8f64b..a390016 100644
--- a/core/java/com/android/internal/app/ResolverComparatorModel.java
+++ b/core/java/com/android/internal/app/ResolverComparatorModel.java
@@ -16,11 +16,11 @@
package com.android.internal.app;
-import android.content.ComponentName;
import android.content.pm.ResolveInfo;
+import com.android.internal.app.chooser.TargetInfo;
+
import java.util.Comparator;
-import java.util.List;
/**
* A ranking model for resolver targets, providing ordering and (optionally) numerical scoring.
@@ -45,7 +45,7 @@
* likelihood that the user will select that component as the target. Implementations that don't
* assign numerical scores are <em>recommended</em> to return a value of 0 for all components.
*/
- float getScore(ComponentName name);
+ float getScore(TargetInfo targetInfo);
/**
* Notify the model that the user selected a target. (Models may log this information, use it as
@@ -53,5 +53,5 @@
* {@code ResolverComparatorModel} instance is immutable, clients will need to get an up-to-date
* instance in order to see any changes in the ranking that might result from this feedback.
*/
- void notifyOnTargetSelected(ComponentName componentName);
+ void notifyOnTargetSelected(TargetInfo targetInfo);
}
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 42b46cd..2df2b2b 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
@@ -157,17 +156,17 @@
/**
* Returns the app share score of the given {@code componentName}.
*/
- public float getScore(ComponentName componentName) {
- return mResolverListController.getScore(componentName);
+ public float getScore(TargetInfo targetInfo) {
+ return mResolverListController.getScore(targetInfo);
}
- public void updateModel(ComponentName componentName) {
- mResolverListController.updateModel(componentName);
+ public void updateModel(TargetInfo targetInfo) {
+ mResolverListController.updateModel(targetInfo);
}
- public void updateChooserCounts(String packageName, String action) {
+ public void updateChooserCounts(String packageName, String action, UserHandle userHandle) {
mResolverListController.updateChooserCounts(
- packageName, getUserHandle().getIdentifier(), action);
+ packageName, userHandle, action);
}
List<ResolvedComponentInfo> getUnfilteredResolveList() {
@@ -440,6 +439,7 @@
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
+ ri.userHandle = getUserHandle();
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
@@ -737,8 +737,10 @@
}
Drawable loadIconForResolveInfo(ResolveInfo ri) {
- // Load icons based on the current process. If in work profile icons should be badged.
- return makePresentationGetter(ri).getIcon(getUserHandle());
+ // Load icons based on userHandle from ResolveInfo. If in work profile/clone profile, icons
+ // should be badged.
+ return makePresentationGetter(ri)
+ .getIcon(ResolverActivity.getResolveInfoUserHandle(ri, getUserHandle()));
}
void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 01dcf962..d9a19b0 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -33,6 +33,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.chooser.DisplayResolveInfo;
+import com.android.internal.app.chooser.TargetInfo;
import java.util.ArrayList;
import java.util.Collections;
@@ -60,6 +61,7 @@
private AbstractResolverComparator mResolverComparator;
private boolean isComputed = false;
+ private final UserHandle mQueryIntentsAsUser;
public ResolverListController(
Context context,
@@ -67,10 +69,17 @@
Intent targetIntent,
String referrerPackage,
int launchedFromUid,
- UserHandle userHandle) {
+ UserHandle userHandle,
+ UserHandle queryIntentsAsUser) {
this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle,
new ResolverRankerServiceResolverComparator(
- context, targetIntent, referrerPackage, null, null));
+ context,
+ targetIntent,
+ referrerPackage,
+ null,
+ null,
+ userHandle),
+ queryIntentsAsUser);
}
public ResolverListController(
@@ -80,7 +89,8 @@
String referrerPackage,
int launchedFromUid,
UserHandle userHandle,
- AbstractResolverComparator resolverComparator) {
+ AbstractResolverComparator resolverComparator,
+ UserHandle queryIntentsAsUser) {
mContext = context;
mpm = pm;
mLaunchedFromUid = launchedFromUid;
@@ -88,6 +98,7 @@
mReferrerPackage = referrerPackage;
mUserHandle = userHandle;
mResolverComparator = resolverComparator;
+ mQueryIntentsAsUser = queryIntentsAsUser;
}
@VisibleForTesting
@@ -113,7 +124,7 @@
boolean shouldGetOnlyDefaultActivities,
List<Intent> intents) {
return getResolversForIntentAsUser(shouldGetResolvedFilter, shouldGetActivityMetadata,
- shouldGetOnlyDefaultActivities, intents, mUserHandle);
+ shouldGetOnlyDefaultActivities, intents, mQueryIntentsAsUser);
}
public List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUser(
@@ -126,7 +137,8 @@
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
- | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
+ | (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0)
+ | PackageManager.MATCH_CLONE_PROFILE;
return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
}
@@ -170,6 +182,10 @@
final int intoCount = into.size();
for (int i = 0; i < fromCount; i++) {
final ResolveInfo newInfo = from.get(i);
+ if (newInfo.userHandle == null) {
+ Log.w(TAG, "Skipping ResolveInfo with no userHandle: " + newInfo);
+ continue;
+ }
boolean found = false;
// Only loop to the end of into as it was before we started; no dupes in from.
for (int j = 0; j < intoCount; j++) {
@@ -388,22 +404,22 @@
@VisibleForTesting
public float getScore(DisplayResolveInfo target) {
- return mResolverComparator.getScore(target.getResolvedComponentName());
+ return mResolverComparator.getScore(target);
}
/**
* Returns the app share score of the given {@code componentName}.
*/
- public float getScore(ComponentName componentName) {
- return mResolverComparator.getScore(componentName);
+ public float getScore(TargetInfo targetInfo) {
+ return mResolverComparator.getScore(targetInfo);
}
- public void updateModel(ComponentName componentName) {
- mResolverComparator.updateModel(componentName);
+ public void updateModel(TargetInfo targetInfo) {
+ mResolverComparator.updateModel(targetInfo);
}
- public void updateChooserCounts(String packageName, int userId, String action) {
- mResolverComparator.updateChooserCounts(packageName, userId, action);
+ public void updateChooserCounts(String packageName, UserHandle user, String action) {
+ mResolverComparator.updateChooserCounts(packageName, user, action);
}
public void destroy() {
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index 9922051..1ecaf21 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -41,9 +41,10 @@
ResolverListAdapter adapter,
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
- UserHandle workProfileUserHandle) {
+ UserHandle workProfileUserHandle,
+ UserHandle cloneUserHandle) {
super(context, /* currentPage */ 0, emptyStateProvider, quietModeManager,
- workProfileUserHandle);
+ workProfileUserHandle, cloneUserHandle);
mItems = new ResolverProfileDescriptor[] {
createProfileDescriptor(adapter)
};
@@ -55,9 +56,10 @@
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
@Profile int defaultProfile,
- UserHandle workProfileUserHandle) {
+ UserHandle workProfileUserHandle,
+ UserHandle cloneUserHandle) {
super(context, /* currentPage */ defaultProfile, emptyStateProvider, quietModeManager,
- workProfileUserHandle);
+ workProfileUserHandle, cloneUserHandle);
mItems = new ResolverProfileDescriptor[] {
createProfileDescriptor(personalAdapter),
createProfileDescriptor(workAdapter)
@@ -107,11 +109,12 @@
@Override
@Nullable
ResolverListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
- if (getActiveListAdapter().getUserHandle().equals(userHandle)) {
- return getActiveListAdapter();
- } else if (getInactiveListAdapter() != null
- && getInactiveListAdapter().getUserHandle().equals(userHandle)) {
- return getInactiveListAdapter();
+ if (getPersonalListAdapter().getUserHandle().equals(userHandle)
+ || userHandle.equals(getCloneUserHandle())) {
+ return getPersonalListAdapter();
+ } else if (getWorkListAdapter() != null
+ && getWorkListAdapter().getUserHandle().equals(userHandle)) {
+ return getWorkListAdapter();
}
return null;
}
diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
index e7f80a7..78c453d 100644
--- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
@@ -17,11 +17,13 @@
package com.android.internal.app;
+import android.annotation.Nullable;
import android.app.usage.UsageStats;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -38,12 +40,16 @@
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+import com.android.internal.app.chooser.TargetInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.google.android.collect.Lists;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -69,10 +75,10 @@
private static final int CONNECTION_COST_TIMEOUT_MILLIS = 200;
private final Collator mCollator;
- private final Map<String, UsageStats> mStats;
+ private final Map<UserHandle, Map<String, UsageStats>> mStatsPerUser;
private final long mCurrentTime;
private final long mSinceTime;
- private final LinkedHashMap<ComponentName, ResolverTarget> mTargetsDict = new LinkedHashMap<>();
+ private final Map<UserHandle, LinkedHashMap<ComponentName, ResolverTarget>> mTargetsDictPerUser;
private final String mReferrerPackage;
private final Object mLock = new Object();
private ArrayList<ResolverTarget> mTargets;
@@ -85,17 +91,34 @@
private CountDownLatch mConnectSignal;
private ResolverRankerServiceComparatorModel mComparatorModel;
- public ResolverRankerServiceResolverComparator(Context context, Intent intent,
+ // context here refers to the activity calling this comparator.
+ // targetUserSpace refers to the userSpace in which the targets to be ranked lie.
+ public ResolverRankerServiceResolverComparator(Context launchedFromContext, Intent intent,
String referrerPackage, AfterCompute afterCompute,
- ChooserActivityLogger chooserActivityLogger) {
- super(context, intent);
- mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
- mReferrerPackage = referrerPackage;
- mContext = context;
+ ChooserActivityLogger chooserActivityLogger, UserHandle targetUserSpace) {
+ this(launchedFromContext, intent, referrerPackage, afterCompute, chooserActivityLogger,
+ Lists.newArrayList(targetUserSpace));
+ }
+ // context here refers to the activity calling this comparator.
+ // targetUserSpaceList refers to the userSpace(s) in which the targets to be ranked lie.
+ public ResolverRankerServiceResolverComparator(Context launchedFromContext, Intent intent,
+ String referrerPackage, AfterCompute afterCompute,
+ ChooserActivityLogger chooserActivityLogger, List<UserHandle> targetUserSpaceList) {
+ super(launchedFromContext, intent, targetUserSpaceList);
+ mCollator = Collator.getInstance(launchedFromContext
+ .getResources().getConfiguration().locale);
+ mReferrerPackage = referrerPackage;
+ mContext = launchedFromContext;
mCurrentTime = System.currentTimeMillis();
mSinceTime = mCurrentTime - USAGE_STATS_PERIOD;
- mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
+ mStatsPerUser = new HashMap<>();
+ mTargetsDictPerUser = new HashMap<>();
+ for (UserHandle user : targetUserSpaceList) {
+ mStatsPerUser.put(user, mUsmMap.get(user)
+ .queryAndAggregateUsageStats(mSinceTime, mCurrentTime));
+ mTargetsDictPerUser.put(user, new LinkedHashMap<>());
+ }
mAction = intent.getAction();
mRankerServiceName = new ComponentName(mContext, this.getClass());
setCallBack(afterCompute);
@@ -147,57 +170,63 @@
for (ResolvedComponentInfo target : targets) {
final ResolverTarget resolverTarget = new ResolverTarget();
- mTargetsDict.put(target.name, resolverTarget);
- final UsageStats pkStats = mStats.get(target.name.getPackageName());
- if (pkStats != null) {
- // Only count recency for apps that weren't the caller
- // since the caller is always the most recent.
- // Persistent processes muck this up, so omit them too.
- if (!target.name.getPackageName().equals(mReferrerPackage)
- && !isPersistentProcess(target)) {
- final float recencyScore =
- (float) Math.max(pkStats.getLastTimeUsed() - recentSinceTime, 0);
- resolverTarget.setRecencyScore(recencyScore);
- if (recencyScore > mostRecencyScore) {
- mostRecencyScore = recencyScore;
- }
- }
- final float timeSpentScore = (float) pkStats.getTotalTimeInForeground();
- resolverTarget.setTimeSpentScore(timeSpentScore);
- if (timeSpentScore > mostTimeSpentScore) {
- mostTimeSpentScore = timeSpentScore;
- }
- final float launchScore = (float) pkStats.mLaunchCount;
- resolverTarget.setLaunchScore(launchScore);
- if (launchScore > mostLaunchScore) {
- mostLaunchScore = launchScore;
- }
-
- float chooserScore = 0.0f;
- if (pkStats.mChooserCounts != null && mAction != null
- && pkStats.mChooserCounts.get(mAction) != null) {
- chooserScore = (float) pkStats.mChooserCounts.get(mAction)
- .getOrDefault(mContentType, 0);
- if (mAnnotations != null) {
- final int size = mAnnotations.length;
- for (int i = 0; i < size; i++) {
- chooserScore += (float) pkStats.mChooserCounts.get(mAction)
- .getOrDefault(mAnnotations[i], 0);
+ final LinkedHashMap<ComponentName, ResolverTarget> targetsDict = mTargetsDictPerUser
+ .get(target.getResolveInfoAt(0).userHandle);
+ final Map<String, UsageStats> stats = mStatsPerUser
+ .get(target.getResolveInfoAt(0).userHandle);
+ if (targetsDict != null && stats != null) {
+ targetsDict.put(target.name, resolverTarget);
+ final UsageStats pkStats = stats.get(target.name.getPackageName());
+ if (pkStats != null) {
+ // Only count recency for apps that weren't the caller
+ // since the caller is always the most recent.
+ // Persistent processes muck this up, so omit them too.
+ if (!target.name.getPackageName().equals(mReferrerPackage)
+ && !isPersistentProcess(target)) {
+ final float recencyScore =
+ (float) Math.max(pkStats.getLastTimeUsed() - recentSinceTime, 0);
+ resolverTarget.setRecencyScore(recencyScore);
+ if (recencyScore > mostRecencyScore) {
+ mostRecencyScore = recencyScore;
}
}
- }
- if (DEBUG) {
- if (mAction == null) {
- Log.d(TAG, "Action type is null");
- } else {
- Log.d(TAG, "Chooser Count of " + mAction + ":" +
- target.name.getPackageName() + " is " +
- Float.toString(chooserScore));
+ final float timeSpentScore = (float) pkStats.getTotalTimeInForeground();
+ resolverTarget.setTimeSpentScore(timeSpentScore);
+ if (timeSpentScore > mostTimeSpentScore) {
+ mostTimeSpentScore = timeSpentScore;
}
- }
- resolverTarget.setChooserScore(chooserScore);
- if (chooserScore > mostChooserScore) {
- mostChooserScore = chooserScore;
+ final float launchScore = (float) pkStats.mLaunchCount;
+ resolverTarget.setLaunchScore(launchScore);
+ if (launchScore > mostLaunchScore) {
+ mostLaunchScore = launchScore;
+ }
+
+ float chooserScore = 0.0f;
+ if (pkStats.mChooserCounts != null && mAction != null
+ && pkStats.mChooserCounts.get(mAction) != null) {
+ chooserScore = (float) pkStats.mChooserCounts.get(mAction)
+ .getOrDefault(mContentType, 0);
+ if (mAnnotations != null) {
+ final int size = mAnnotations.length;
+ for (int i = 0; i < size; i++) {
+ chooserScore += (float) pkStats.mChooserCounts.get(mAction)
+ .getOrDefault(mAnnotations[i], 0);
+ }
+ }
+ }
+ if (DEBUG) {
+ if (mAction == null) {
+ Log.d(TAG, "Action type is null");
+ } else {
+ Log.d(TAG, "Chooser Count of " + mAction + ":"
+ + target.name.getPackageName() + " is "
+ + Float.toString(chooserScore));
+ }
+ }
+ resolverTarget.setChooserScore(chooserScore);
+ if (chooserScore > mostChooserScore) {
+ mostChooserScore = chooserScore;
+ }
}
}
}
@@ -209,7 +238,11 @@
+ " mostChooserScore: " + mostChooserScore);
}
- mTargets = new ArrayList<>(mTargetsDict.values());
+ mTargets = new ArrayList<>();
+ for (UserHandle u : mTargetsDictPerUser.keySet()) {
+ mTargets.addAll(mTargetsDictPerUser.get(u).values());
+ }
+
for (ResolverTarget target : mTargets) {
final float recency = target.getRecencyScore() / mostRecencyScore;
setFeatures(target, recency * recency * RECENCY_MULTIPLIER,
@@ -232,15 +265,15 @@
}
@Override
- public float getScore(ComponentName name) {
- return mComparatorModel.getScore(name);
+ public float getScore(TargetInfo targetInfo) {
+ return mComparatorModel.getScore(targetInfo);
}
// update ranking model when the connection to it is valid.
@Override
- public void updateModel(ComponentName componentName) {
+ public void updateModel(TargetInfo targetInfo) {
synchronized (mLock) {
- mComparatorModel.notifyOnTargetSelected(componentName);
+ mComparatorModel.notifyOnTargetSelected(targetInfo);
}
}
@@ -281,7 +314,8 @@
// resolve the service for ranking.
private Intent resolveRankerService() {
Intent intent = new Intent(ResolverRankerService.SERVICE_INTERFACE);
- final List<ResolveInfo> resolveInfos = mPm.queryIntentServices(intent, 0);
+ final List<ResolveInfo> resolveInfos = mContext.getPackageManager()
+ .queryIntentServices(intent, 0);
for (ResolveInfo resolveInfo : resolveInfos) {
if (resolveInfo == null || resolveInfo.serviceInfo == null
|| resolveInfo.serviceInfo.applicationInfo == null) {
@@ -294,7 +328,8 @@
resolveInfo.serviceInfo.applicationInfo.packageName,
resolveInfo.serviceInfo.name);
try {
- final String perm = mPm.getServiceInfo(componentName, 0).permission;
+ final String perm = mContext.getPackageManager()
+ .getServiceInfo(componentName, 0).permission;
if (!ResolverRankerService.BIND_PERMISSION.equals(perm)) {
Log.w(TAG, "ResolverRankerService " + componentName + " does not require"
+ " permission " + ResolverRankerService.BIND_PERMISSION
@@ -305,9 +340,9 @@
+ " in the manifest.");
continue;
}
- if (PackageManager.PERMISSION_GRANTED != mPm.checkPermission(
- ResolverRankerService.HOLD_PERMISSION,
- resolveInfo.serviceInfo.packageName)) {
+ if (PackageManager.PERMISSION_GRANTED != mContext.getPackageManager()
+ .checkPermission(ResolverRankerService.HOLD_PERMISSION,
+ resolveInfo.serviceInfo.packageName)) {
Log.w(TAG, "ResolverRankerService " + componentName + " does not hold"
+ " permission " + ResolverRankerService.HOLD_PERMISSION
+ " - this service will not be queried for "
@@ -385,7 +420,9 @@
@Override
void beforeCompute() {
super.beforeCompute();
- mTargetsDict.clear();
+ for (UserHandle userHandle : mTargetsDictPerUser.keySet()) {
+ mTargetsDictPerUser.get(userHandle).clear();
+ }
mTargets = null;
mRankerServiceName = new ComponentName(mContext, this.getClass());
mComparatorModel = buildUpdatedModel();
@@ -465,14 +502,14 @@
// so the ResolverComparatorModel may provide inconsistent results. We should make immutable
// copies of the data (waiting for any necessary remaining data before creating the model).
return new ResolverRankerServiceComparatorModel(
- mStats,
- mTargetsDict,
+ mStatsPerUser,
+ mTargetsDictPerUser,
mTargets,
mCollator,
mRanker,
mRankerServiceName,
(mAnnotations != null),
- mPm);
+ mPmMap);
}
/**
@@ -481,35 +518,36 @@
* removing the complex legacy API.
*/
static class ResolverRankerServiceComparatorModel implements ResolverComparatorModel {
- private final Map<String, UsageStats> mStats; // Treat as immutable.
- private final Map<ComponentName, ResolverTarget> mTargetsDict; // Treat as immutable.
+ private final Map<UserHandle, Map<String, UsageStats>> mStatsPerUser; // Treat as immutable.
+ private final Map<UserHandle, LinkedHashMap<ComponentName,
+ ResolverTarget>> mTargetsDictPerUser; // Treat as immutable.
private final List<ResolverTarget> mTargets; // Treat as immutable.
private final Collator mCollator;
private final IResolverRankerService mRanker;
private final ComponentName mRankerServiceName;
private final boolean mAnnotationsUsed;
- private final PackageManager mPm;
+ private final Map<UserHandle, PackageManager> mPmMap;
// TODO: it doesn't look like we should have to pass both targets and targetsDict, but it's
// not written in a way that makes it clear whether we can derive one from the other (at
// least in this constructor).
ResolverRankerServiceComparatorModel(
- Map<String, UsageStats> stats,
- Map<ComponentName, ResolverTarget> targetsDict,
+ Map<UserHandle, Map<String, UsageStats>> statsPerUser,
+ Map<UserHandle, LinkedHashMap<ComponentName, ResolverTarget>> targetsDictPerUser,
List<ResolverTarget> targets,
Collator collator,
IResolverRankerService ranker,
ComponentName rankerServiceName,
boolean annotationsUsed,
- PackageManager pm) {
- mStats = stats;
- mTargetsDict = targetsDict;
+ Map<UserHandle, PackageManager> pmMap) {
+ mStatsPerUser = statsPerUser;
+ mTargetsDictPerUser = targetsDictPerUser;
mTargets = targets;
mCollator = collator;
mRanker = ranker;
mRankerServiceName = rankerServiceName;
mAnnotationsUsed = annotationsUsed;
- mPm = pm;
+ mPmMap = pmMap;
}
@Override
@@ -518,25 +556,29 @@
// a bug there, or do we have a way of knowing it will be non-null under certain
// conditions?
return (lhs, rhs) -> {
- if (mStats != null) {
- final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName(
- lhs.activityInfo.packageName, lhs.activityInfo.name));
- final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName(
- rhs.activityInfo.packageName, rhs.activityInfo.name));
+ final ResolverTarget lhsTarget = getActivityResolverTargetForUser(lhs.activityInfo,
+ lhs.userHandle);
+ final ResolverTarget rhsTarget = getActivityResolverTargetForUser(rhs.activityInfo,
+ rhs.userHandle);
- if (lhsTarget != null && rhsTarget != null) {
- final int selectProbabilityDiff = Float.compare(
- rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability());
+ if (lhsTarget != null && rhsTarget != null) {
+ final int selectProbabilityDiff = Float.compare(
+ rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability());
- if (selectProbabilityDiff != 0) {
- return selectProbabilityDiff > 0 ? 1 : -1;
- }
+ if (selectProbabilityDiff != 0) {
+ return selectProbabilityDiff > 0 ? 1 : -1;
}
}
- CharSequence sa = lhs.loadLabel(mPm);
+ CharSequence sa = null;
+ if (mPmMap.containsKey(lhs.userHandle)) {
+ sa = lhs.loadLabel(mPmMap.get(lhs.userHandle));
+ }
if (sa == null) sa = lhs.activityInfo.name;
- CharSequence sb = rhs.loadLabel(mPm);
+ CharSequence sb = null;
+ if (mPmMap.containsKey(rhs.userHandle)) {
+ sb = rhs.loadLabel(mPmMap.get(rhs.userHandle));
+ }
if (sb == null) sb = rhs.activityInfo.name;
return mCollator.compare(sa.toString().trim(), sb.toString().trim());
@@ -544,22 +586,28 @@
}
@Override
- public float getScore(ComponentName name) {
- final ResolverTarget target = mTargetsDict.get(name);
- if (target != null) {
- return target.getSelectProbability();
+ public float getScore(TargetInfo targetInfo) {
+ if (mTargetsDictPerUser.containsKey(targetInfo.getResolveInfo().userHandle)
+ && mTargetsDictPerUser.get(targetInfo.getResolveInfo().userHandle)
+ .get(targetInfo.getResolvedComponentName()) != null) {
+ return mTargetsDictPerUser.get(targetInfo.getResolveInfo().userHandle)
+ .get(targetInfo.getResolvedComponentName()).getSelectProbability();
}
return 0;
}
@Override
- public void notifyOnTargetSelected(ComponentName componentName) {
+ public void notifyOnTargetSelected(TargetInfo targetInfo) {
if (mRanker != null) {
try {
- int selectedPos = new ArrayList<ComponentName>(mTargetsDict.keySet())
- .indexOf(componentName);
+ int selectedPos = -1;
+ if (mTargetsDictPerUser.containsKey(targetInfo.getResolveInfo().userHandle)) {
+ selectedPos = new ArrayList<>(mTargetsDictPerUser
+ .get(targetInfo.getResolveInfo().userHandle).keySet())
+ .indexOf(targetInfo.getResolvedComponentName());
+ }
if (selectedPos >= 0 && mTargets != null) {
- final float selectedProbability = getScore(componentName);
+ final float selectedProbability = getScore(targetInfo);
int order = 0;
for (ResolverTarget target : mTargets) {
if (target.getSelectProbability() > selectedProbability) {
@@ -570,7 +618,8 @@
mRanker.train(mTargets, selectedPos);
} else {
if (DEBUG) {
- Log.d(TAG, "Selected a unknown component: " + componentName);
+ Log.d(TAG, "Selected a unknown component: " + targetInfo
+ .getResolvedComponentName());
}
}
} catch (RemoteException e) {
@@ -594,5 +643,16 @@
metricsLogger.write(log);
}
}
+
+ @Nullable
+ private ResolverTarget getActivityResolverTargetForUser(
+ ActivityInfo activity, UserHandle user) {
+ if ((mStatsPerUser == null) || !mTargetsDictPerUser.containsKey(user)) {
+ return null;
+ }
+ return mTargetsDictPerUser
+ .get(user)
+ .get(new ComponentName(activity.packageName, activity.name));
+ }
}
}
diff --git a/core/java/com/android/internal/app/SystemLocaleCollector.java b/core/java/com/android/internal/app/SystemLocaleCollector.java
index 9a6d4c1..416f510 100644
--- a/core/java/com/android/internal/app/SystemLocaleCollector.java
+++ b/core/java/com/android/internal/app/SystemLocaleCollector.java
@@ -26,9 +26,15 @@
/** The Locale data collector for System language. */
class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
private final Context mContext;
+ private LocaleList mExplicitLocales;
SystemLocaleCollector(Context context) {
+ this(context, null);
+ }
+
+ SystemLocaleCollector(Context context, LocaleList explicitLocales) {
mContext = context;
+ mExplicitLocales = explicitLocales;
}
@Override
@@ -47,18 +53,16 @@
boolean translatedOnly, boolean isForCountryMode) {
Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly);
Set<LocaleStore.LocaleInfo> localeList;
-
if (isForCountryMode) {
localeList = LocaleStore.getLevelLocales(mContext,
- langTagsToIgnore, parent, translatedOnly);
+ langTagsToIgnore, parent, translatedOnly, mExplicitLocales);
} else {
localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore,
- null /* no parent */, translatedOnly);
+ null /* no parent */, translatedOnly, mExplicitLocales);
}
return localeList;
}
-
@Override
public boolean hasSpecificPackageName() {
return false;
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 72b9cd2..818a503 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -73,6 +73,7 @@
import java.io.PrintWriter;
import java.util.Comparator;
+import java.util.concurrent.TimeUnit;
public final class ProcessState {
private static final String TAG = "ProcessStats";
@@ -1542,6 +1543,75 @@
proto.write(fieldId, procName);
}
+ /** Dumps the duration of each state to statsEventOutput. */
+ public void dumpStateDurationToStatsd(
+ int atomTag, ProcessStats processStats, StatsEventOutput statsEventOutput) {
+ long topMs = 0;
+ long fgsMs = 0;
+ long boundTopMs = 0;
+ long boundFgsMs = 0;
+ long importantForegroundMs = 0;
+ long cachedMs = 0;
+ long frozenMs = 0;
+ long otherMs = 0;
+ for (int i = 0, size = mDurations.getKeyCount(); i < size; i++) {
+ final int key = mDurations.getKeyAt(i);
+ final int type = SparseMappingTable.getIdFromKey(key);
+ int procStateIndex = type % STATE_COUNT;
+ long duration = mDurations.getValue(key);
+ switch (procStateIndex) {
+ case STATE_TOP:
+ topMs += duration;
+ break;
+ case STATE_BOUND_TOP_OR_FGS:
+ boundTopMs += duration;
+ break;
+ case STATE_FGS:
+ fgsMs += duration;
+ break;
+ case STATE_IMPORTANT_FOREGROUND:
+ case STATE_IMPORTANT_BACKGROUND:
+ importantForegroundMs += duration;
+ break;
+ case STATE_BACKUP:
+ case STATE_SERVICE:
+ case STATE_SERVICE_RESTARTING:
+ case STATE_RECEIVER:
+ case STATE_HEAVY_WEIGHT:
+ case STATE_HOME:
+ case STATE_LAST_ACTIVITY:
+ case STATE_PERSISTENT:
+ otherMs += duration;
+ break;
+ case STATE_CACHED_ACTIVITY:
+ case STATE_CACHED_ACTIVITY_CLIENT:
+ case STATE_CACHED_EMPTY:
+ cachedMs += duration;
+ break;
+ // TODO (b/261910877) Add support for tracking boundFgsMs and
+ // frozenMs.
+ }
+ }
+ statsEventOutput.write(
+ atomTag,
+ getUid(),
+ getName(),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ processStats.mTimePeriodEndUptime
+ - processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(topMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(fgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundTopMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundFgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(importantForegroundMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(cachedMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(frozenMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(otherMs));
+ }
+
/** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
String procName, int uid, long now,
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index d2b2f0a..f3ed09a 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -43,6 +43,7 @@
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.AssociationState.SourceKey;
import com.android.internal.app.procstats.AssociationState.SourceState;
+import com.android.internal.util.function.QuintConsumer;
import dalvik.system.VMRuntime;
@@ -56,6 +57,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -2389,6 +2392,79 @@
}
}
+ void forEachProcess(Consumer<ProcessState> consumer) {
+ final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+ for (int ip = 0, size = procMap.size(); ip < size; ip++) {
+ final SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final ProcessState processState = uids.valueAt(iu);
+ consumer.accept(processState);
+ }
+ }
+ }
+
+ void forEachAssociation(
+ QuintConsumer<AssociationState, Integer, String, SourceKey, SourceState> consumer) {
+ final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+ mPackages.getMap();
+ for (int ip = 0, size = pkgMap.size(); ip < size; ip++) {
+ final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final int uid = uids.keyAt(iu);
+ final LongSparseArray<PackageState> versions = uids.valueAt(iu);
+ for (int iv = 0, versionsSize = versions.size(); iv < versionsSize; iv++) {
+ final PackageState state = versions.valueAt(iv);
+ for (int iasc = 0, ascSize = state.mAssociations.size();
+ iasc < ascSize;
+ iasc++) {
+ final String serviceName = state.mAssociations.keyAt(iasc);
+ final AssociationState asc = state.mAssociations.valueAt(iasc);
+ for (int is = 0, sourcesSize = asc.mSources.size();
+ is < sourcesSize;
+ is++) {
+ final SourceState src = asc.mSources.valueAt(is);
+ final SourceKey key = asc.mSources.keyAt(is);
+ consumer.accept(asc, uid, serviceName, key, src);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** Dumps the stats of all processes to statsEventOutput. */
+ public void dumpProcessState(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachProcess(
+ (processState) -> {
+ if (processState.isMultiPackage()
+ && processState.getCommonProcess() != processState) {
+ return;
+ }
+ processState.dumpStateDurationToStatsd(atomTag, this, statsEventOutput);
+ });
+ }
+
+ /** Dumps all process association data to statsEventOutput. */
+ public void dumpProcessAssociation(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachAssociation(
+ (asc, serviceUid, serviceName, key, src) -> {
+ statsEventOutput.write(
+ atomTag,
+ key.mUid,
+ key.mProcess,
+ serviceUid,
+ serviceName,
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ mTimePeriodEndUptime - mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(src.mDuration),
+ src.mActiveCount,
+ asc.getProcessName());
+ });
+ }
+
private void dumpProtoPreamble(ProtoOutputStream proto) {
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
diff --git a/core/java/com/android/internal/app/procstats/StatsEventOutput.java b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
new file mode 100644
index 0000000..b2e4054
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+import android.util.StatsEvent;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.List;
+
+/**
+ * A simple wrapper of FrameworkStatsLog.buildStatsEvent. This allows unit tests to mock out the
+ * dependency.
+ */
+public class StatsEventOutput {
+
+ List<StatsEvent> mOutput;
+
+ public StatsEventOutput(List<StatsEvent> output) {
+ mOutput = output;
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int uid,
+ String processName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int topSeconds,
+ int fgsSeconds,
+ int boundTopSeconds,
+ int boundFgsSeconds,
+ int importantForegroundSeconds,
+ int cachedSeconds,
+ int frozenSeconds,
+ int otherSeconds) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ uid,
+ processName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ topSeconds,
+ fgsSeconds,
+ boundTopSeconds,
+ boundFgsSeconds,
+ importantForegroundSeconds,
+ cachedSeconds,
+ frozenSeconds,
+ otherSeconds));
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int clientUid,
+ String processName,
+ int serviceUid,
+ String serviceName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int activeDurationUptimeSecs,
+ int activeCount,
+ String serviceProcessName) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ clientUid,
+ processName,
+ serviceUid,
+ serviceName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ activeDurationUptimeSecs,
+ activeCount,
+ serviceProcessName));
+ }
+}
diff --git a/core/java/com/android/internal/content/InstallLocationUtils.java b/core/java/com/android/internal/content/InstallLocationUtils.java
index 4d9c09e..a173ce1 100644
--- a/core/java/com/android/internal/content/InstallLocationUtils.java
+++ b/core/java/com/android/internal/content/InstallLocationUtils.java
@@ -292,7 +292,7 @@
// For new installations of a predefined size, check property to let it through
// regardless of the actual free space.
- if (bestCandidate != null && Integer.MAX_VALUE == params.sizeBytes
+ if (!volumePaths.isEmpty() && Integer.MAX_VALUE == params.sizeBytes
&& SystemProperties.getBoolean("debug.pm.install_skip_size_check_for_maxint",
false)) {
return bestCandidate;
diff --git a/core/java/com/android/internal/inputmethod/EditableInputConnection.java b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
index 8690e8d..3020d77 100644
--- a/core/java/com/android/internal/inputmethod/EditableInputConnection.java
+++ b/core/java/com/android/internal/inputmethod/EditableInputConnection.java
@@ -44,6 +44,7 @@
import android.view.inputmethod.HandwritingGesture;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.InsertModeGesture;
import android.view.inputmethod.JoinOrSplitGesture;
import android.view.inputmethod.PreviewableHandwritingGesture;
import android.view.inputmethod.RemoveSpaceGesture;
@@ -314,6 +315,8 @@
result = mTextView.performHandwritingRemoveSpaceGesture((RemoveSpaceGesture) gesture);
} else if (gesture instanceof JoinOrSplitGesture) {
result = mTextView.performHandwritingJoinOrSplitGesture((JoinOrSplitGesture) gesture);
+ } else if (gesture instanceof InsertModeGesture) {
+ result = mTextView.performHandwritingInsertModeGesture((InsertModeGesture) gesture);
} else {
result = HANDWRITING_GESTURE_RESULT_UNSUPPORTED;
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 95a47ea..d9e9a5f 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,15 +16,11 @@
package com.android.internal.jank;
-import static android.Manifest.permission.READ_DEVICE_CONFIG;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
import static com.android.internal.jank.FrameTracker.REASON_CANCEL_NORMAL;
import static com.android.internal.jank.FrameTracker.REASON_CANCEL_TIMEOUT;
import static com.android.internal.jank.FrameTracker.REASON_END_NORMAL;
import static com.android.internal.jank.FrameTracker.REASON_END_UNKNOWN;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__BIOMETRIC_PROMPT_TRANSITION;
-import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
@@ -93,19 +89,17 @@
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__VOLUME_CONTROL;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__WALLPAPER_TRANSITION;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
import android.annotation.UiThread;
import android.annotation.WorkerThread;
-import android.app.ActivityThread;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
@@ -238,7 +232,6 @@
public static final int CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS = 66;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE = 67;
public static final int CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME = 68;
- public static final int CUJ_IME_INSETS_ANIMATION = 69;
private static final int NO_STATSD_LOGGING = -1;
@@ -316,7 +309,6 @@
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_SWIPE_TO_RECENTS,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_SWIPE,
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
- UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__IME_INSETS_ANIMATION,
};
private static class InstanceHolder {
@@ -409,8 +401,7 @@
CUJ_RECENTS_SCROLLING,
CUJ_LAUNCHER_APP_SWIPE_TO_RECENTS,
CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
- CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
- CUJ_IME_INSETS_ANIMATION,
+ CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME
})
@Retention(RetentionPolicy.SOURCE)
public @interface CujType {
@@ -431,37 +422,29 @@
* @param worker the worker thread for the callbacks
*/
@VisibleForTesting
- @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
public InteractionJankMonitor(@NonNull HandlerThread worker) {
+ // Check permission early.
+ Settings.Config.enforceReadPermission(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR);
+
mRunningTrackers = new SparseArray<>();
mTimeoutActions = new SparseArray<>();
mWorker = worker;
mWorker.start();
- mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
- mEnabled = DEFAULT_ENABLED;
+ mDisplayResolutionTracker = new DisplayResolutionTracker(worker.getThreadHandler());
- final Context context = ActivityThread.currentApplication();
- if (context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
- // Post initialization to the background in case we're running on the main thread.
- mWorker.getThreadHandler().post(
- () -> mPropertiesChangedListener.onPropertiesChanged(
- DeviceConfig.getProperties(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
- new HandlerExecutor(mWorker.getThreadHandler()),
- mPropertiesChangedListener);
- } else {
- if (DEBUG) {
- Log.d(TAG, "Initialized the InteractionJankMonitor."
- + " (No READ_DEVICE_CONFIG permission to change configs)"
- + " enabled=" + mEnabled + ", interval=" + mSamplingInterval
- + ", missedFrameThreshold=" + mTraceThresholdMissedFrames
- + ", frameTimeThreshold=" + mTraceThresholdFrameTimeMillis
- + ", package=" + context.getPackageName());
- }
- }
+ // Post initialization to the background in case we're running on the main
+ // thread.
+ mWorker.getThreadHandler().post(
+ () -> mPropertiesChangedListener.onPropertiesChanged(
+ DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
+ new HandlerExecutor(mWorker.getThreadHandler()),
+ mPropertiesChangedListener);
+ mEnabled = DEFAULT_ENABLED;
}
/**
@@ -940,8 +923,6 @@
return "LAUNCHER_CLOSE_ALL_APPS_SWIPE";
case CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME:
return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
- case CUJ_IME_INSETS_ANIMATION:
- return "IME_INSETS_ANIMATION";
}
return "UNKNOWN";
}
@@ -1197,7 +1178,7 @@
*/
@VisibleForTesting
public int getDisplayId() {
- return mSurfaceOnly ? mContext.getDisplayId() : mView.getContext().getDisplayId();
+ return (mSurfaceOnly ? mContext.getDisplay() : mView.getDisplay()).getDisplayId();
}
}
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index af205d2..40d5c47 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -50,9 +50,6 @@
public static final boolean CONFIG_SMALL_BATTERY =
SystemProperties.getBoolean("ro.config.small_battery", false);
- // ------ ro.fw.* ------------ //
- public static final boolean FW_SYSTEM_USER_SPLIT =
- SystemProperties.getBoolean("ro.fw.system_user_split", false);
/**
* Indicates whether the device should run in headless system user mode,
* in which user 0 only runs the system, not a real user.
diff --git a/core/java/com/android/internal/power/EnergyConsumerStats.java b/core/java/com/android/internal/power/EnergyConsumerStats.java
index 8cf17cda..e2098dd 100644
--- a/core/java/com/android/internal/power/EnergyConsumerStats.java
+++ b/core/java/com/android/internal/power/EnergyConsumerStats.java
@@ -59,7 +59,8 @@
public static final int POWER_BUCKET_GNSS = 6;
public static final int POWER_BUCKET_MOBILE_RADIO = 7;
public static final int POWER_BUCKET_CAMERA = 8;
- public static final int NUMBER_STANDARD_POWER_BUCKETS = 9; // Buckets above this are custom.
+ public static final int POWER_BUCKET_PHONE = 9;
+ public static final int NUMBER_STANDARD_POWER_BUCKETS = 10; // Buckets above this are custom.
@IntDef(prefix = {"POWER_BUCKET_"}, value = {
POWER_BUCKET_UNKNOWN,
@@ -72,6 +73,7 @@
POWER_BUCKET_GNSS,
POWER_BUCKET_MOBILE_RADIO,
POWER_BUCKET_CAMERA,
+ POWER_BUCKET_PHONE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StandardPowerBucket {
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 8f943ef..ad1fdba 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -79,7 +79,9 @@
Consts.TAG_WM),
WM_DEBUG_SYNC_ENGINE(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM),
- WM_DEBUG_WINDOW_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+ WM_DEBUG_WINDOW_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+ Consts.TAG_WM),
+ WM_DEBUG_WINDOW_TRANSITIONS_MIN(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM),
WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM),
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 2d5bb6c..afb526a 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -14,10 +14,7 @@
package com.android.internal.util;
-import static android.Manifest.permission.READ_DEVICE_CONFIG;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_APP;
-import static android.provider.DeviceConfig.NAMESPACE_LATENCY_TRACKER;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_CHECK_CREDENTIAL_UNLOCKED;
@@ -27,8 +24,6 @@
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOAD_SHARE_SHEET;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK;
-import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN;
-import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK;
import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR;
@@ -47,12 +42,9 @@
import static com.android.internal.util.LatencyTracker.ActionProperties.SAMPLE_INTERVAL_SUFFIX;
import static com.android.internal.util.LatencyTracker.ActionProperties.TRACE_THRESHOLD_SUFFIX;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.app.ActivityThread;
import android.content.Context;
import android.os.Build;
import android.os.ConditionVariable;
@@ -195,16 +187,6 @@
*/
public static final int ACTION_SHOW_VOICE_INTERACTION = 19;
- /**
- * Time it takes to request IME shown animation.
- */
- public static final int ACTION_REQUEST_IME_SHOWN = 20;
-
- /**
- * Time it takes to request IME hidden animation.
- */
- public static final int ACTION_REQUEST_IME_HIDDEN = 21;
-
private static final int[] ACTIONS_ALL = {
ACTION_EXPAND_PANEL,
ACTION_TOGGLE_RECENTS,
@@ -226,8 +208,6 @@
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
- ACTION_REQUEST_IME_SHOWN,
- ACTION_REQUEST_IME_HIDDEN,
};
/** @hide */
@@ -252,8 +232,6 @@
ACTION_SHOW_SELECTION_TOOLBAR,
ACTION_FOLD_TO_AOD,
ACTION_SHOW_VOICE_INTERACTION,
- ACTION_REQUEST_IME_SHOWN,
- ACTION_REQUEST_IME_HIDDEN,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
@@ -281,8 +259,6 @@
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_FOLD_TO_AOD,
UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION,
- UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN,
- UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN,
};
private static LatencyTracker sLatencyTracker;
@@ -308,30 +284,15 @@
return sLatencyTracker;
}
- @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
@VisibleForTesting
public LatencyTracker() {
mEnabled = DEFAULT_ENABLED;
- final Context context = ActivityThread.currentApplication();
- if (context != null
- && context.checkCallingOrSelfPermission(READ_DEVICE_CONFIG) == PERMISSION_GRANTED) {
- // Post initialization to the background in case we're running on the main thread.
- BackgroundThread.getHandler().post(() -> this.updateProperties(
- DeviceConfig.getProperties(NAMESPACE_LATENCY_TRACKER)));
- DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_LATENCY_TRACKER,
- BackgroundThread.getExecutor(), this::updateProperties);
- } else {
- if (DEBUG) {
- if (context == null) {
- Log.d(TAG, "No application for " + ActivityThread.currentActivityThread());
- } else {
- Log.d(TAG, "Initialized the LatencyTracker."
- + " (No READ_DEVICE_CONFIG permission to change configs)"
- + " enabled=" + mEnabled + ", package=" + context.getPackageName());
- }
- }
- }
+ // Post initialization to the background in case we're running on the main thread.
+ BackgroundThread.getHandler().post(() -> this.updateProperties(
+ DeviceConfig.getProperties(DeviceConfig.NAMESPACE_LATENCY_TRACKER)));
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_LATENCY_TRACKER,
+ BackgroundThread.getExecutor(), this::updateProperties);
}
private void updateProperties(DeviceConfig.Properties properties) {
@@ -407,10 +368,6 @@
return "ACTION_FOLD_TO_AOD";
case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION:
return "ACTION_SHOW_VOICE_INTERACTION";
- case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_SHOWN:
- return "ACTION_REQUEST_IME_SHOWN";
- case UIACTION_LATENCY_REPORTED__ACTION__ACTION_REQUEST_IME_HIDDEN:
- return "ACTION_REQUEST_IME_HIDDEN";
default:
throw new IllegalArgumentException("Invalid action");
}
diff --git a/core/java/com/android/internal/util/ObservableServiceConnection.java b/core/java/com/android/internal/util/ObservableServiceConnection.java
index 3165d29..45256fd 100644
--- a/core/java/com/android/internal/util/ObservableServiceConnection.java
+++ b/core/java/com/android/internal/util/ObservableServiceConnection.java
@@ -165,6 +165,13 @@
}
/**
+ * Executes code on the executor specified at construction.
+ */
+ public void execute(Runnable runnable) {
+ mExecutor.execute(runnable);
+ }
+
+ /**
* Initiate binding to the service.
*
* @return {@code true} if initiating binding succeed, {@code false} if the binding failed or
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 79c5196..3a393b6 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -1,7 +1,7 @@
package com.android.internal.util;
import static android.content.Intent.ACTION_USER_SWITCHED;
-import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
+import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -11,29 +11,18 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.graphics.Bitmap;
-import android.graphics.ColorSpace;
-import android.graphics.Insets;
-import android.graphics.ParcelableColorSpace;
-import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
import android.net.Uri;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.WindowManager.ScreenshotSource;
-import android.view.WindowManager.ScreenshotType;
import com.android.internal.annotations.VisibleForTesting;
-import java.util.Objects;
import java.util.function.Consumer;
public class ScreenshotHelper {
@@ -41,212 +30,6 @@
public static final int SCREENSHOT_MSG_URI = 1;
public static final int SCREENSHOT_MSG_PROCESS_COMPLETE = 2;
- /**
- * Describes a screenshot request.
- */
- public static class ScreenshotRequest implements Parcelable {
- @ScreenshotType
- private final int mType;
-
- @ScreenshotSource
- private final int mSource;
-
- private final Bundle mBitmapBundle;
- private final Rect mBoundsInScreen;
- private final Insets mInsets;
- private final int mTaskId;
- private final int mUserId;
- private final ComponentName mTopComponent;
-
-
- public ScreenshotRequest(@ScreenshotType int type, @ScreenshotSource int source) {
- this(type, source, /* topComponent */ null);
- }
-
- public ScreenshotRequest(@ScreenshotType int type, @ScreenshotSource int source,
- ComponentName topComponent) {
- this(type,
- source,
- /* bitmapBundle*/ null,
- /* boundsInScreen */ null,
- /* insets */ null,
- /* taskId */ -1,
- /* userId */ -1,
- topComponent);
- }
-
- public ScreenshotRequest(@ScreenshotType int type, @ScreenshotSource int source,
- Bundle bitmapBundle, Rect boundsInScreen, Insets insets, int taskId, int userId,
- ComponentName topComponent) {
- mType = type;
- mSource = source;
- mBitmapBundle = bitmapBundle;
- mBoundsInScreen = boundsInScreen;
- mInsets = insets;
- mTaskId = taskId;
- mUserId = userId;
- mTopComponent = topComponent;
- }
-
- ScreenshotRequest(Parcel in) {
- mType = in.readInt();
- mSource = in.readInt();
- if (in.readInt() == 1) {
- mBitmapBundle = in.readBundle(getClass().getClassLoader());
- mBoundsInScreen = in.readParcelable(Rect.class.getClassLoader(), Rect.class);
- mInsets = in.readParcelable(Insets.class.getClassLoader(), Insets.class);
- mTaskId = in.readInt();
- mUserId = in.readInt();
- mTopComponent = in.readParcelable(ComponentName.class.getClassLoader(),
- ComponentName.class);
- } else {
- mBitmapBundle = null;
- mBoundsInScreen = null;
- mInsets = null;
- mTaskId = -1;
- mUserId = -1;
- mTopComponent = null;
- }
- }
-
- @ScreenshotType
- public int getType() {
- return mType;
- }
-
- @ScreenshotSource
- public int getSource() {
- return mSource;
- }
-
- public Bundle getBitmapBundle() {
- return mBitmapBundle;
- }
-
- public Rect getBoundsInScreen() {
- return mBoundsInScreen;
- }
-
- public Insets getInsets() {
- return mInsets;
- }
-
- public int getTaskId() {
- return mTaskId;
- }
-
- public int getUserId() {
- return mUserId;
- }
-
- public ComponentName getTopComponent() {
- return mTopComponent;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mType);
- dest.writeInt(mSource);
- if (mBitmapBundle == null) {
- dest.writeInt(0);
- } else {
- dest.writeInt(1);
- dest.writeBundle(mBitmapBundle);
- dest.writeParcelable(mBoundsInScreen, 0);
- dest.writeParcelable(mInsets, 0);
- dest.writeInt(mTaskId);
- dest.writeInt(mUserId);
- dest.writeParcelable(mTopComponent, 0);
- }
- }
-
- @NonNull
- public static final Parcelable.Creator<ScreenshotRequest> CREATOR =
- new Parcelable.Creator<ScreenshotRequest>() {
-
- @Override
- public ScreenshotRequest createFromParcel(Parcel source) {
- return new ScreenshotRequest(source);
- }
-
- @Override
- public ScreenshotRequest[] newArray(int size) {
- return new ScreenshotRequest[size];
- }
- };
- }
-
- /**
- * Bundler used to convert between a hardware bitmap and a bundle without copying the internal
- * content. This is expected to be used together with {@link #provideScreenshot} to handle a
- * hardware bitmap as a screenshot.
- */
- public static final class HardwareBitmapBundler {
- private static final String KEY_BUFFER = "bitmap_util_buffer";
- private static final String KEY_COLOR_SPACE = "bitmap_util_color_space";
-
- private HardwareBitmapBundler() {
- }
-
- /**
- * Creates a Bundle that represents the given Bitmap.
- * <p>The Bundle will contain a wrapped version of the Bitmaps HardwareBuffer, so will avoid
- * copies when passing across processes, only pass to processes you trust.
- *
- * <p>Returns a new Bundle rather than modifying an exiting one to avoid key collisions, the
- * returned Bundle should be treated as a standalone object.
- *
- * @param bitmap to convert to bundle
- * @return a Bundle representing the bitmap, should only be parsed by
- * {@link #bundleToHardwareBitmap(Bundle)}
- */
- public static Bundle hardwareBitmapToBundle(Bitmap bitmap) {
- if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
- throw new IllegalArgumentException(
- "Passed bitmap must have hardware config, found: " + bitmap.getConfig());
- }
-
- // Bitmap assumes SRGB for null color space
- ParcelableColorSpace colorSpace =
- bitmap.getColorSpace() == null
- ? new ParcelableColorSpace(ColorSpace.get(ColorSpace.Named.SRGB))
- : new ParcelableColorSpace(bitmap.getColorSpace());
-
- Bundle bundle = new Bundle();
- bundle.putParcelable(KEY_BUFFER, bitmap.getHardwareBuffer());
- bundle.putParcelable(KEY_COLOR_SPACE, colorSpace);
-
- return bundle;
- }
-
- /**
- * Extracts the Bitmap added to a Bundle with {@link #hardwareBitmapToBundle(Bitmap)} .}
- *
- * <p>This Bitmap contains the HardwareBuffer from the original caller, be careful passing
- * this Bitmap on to any other source.
- *
- * @param bundle containing the bitmap
- * @return a hardware Bitmap
- */
- public static Bitmap bundleToHardwareBitmap(Bundle bundle) {
- if (!bundle.containsKey(KEY_BUFFER) || !bundle.containsKey(KEY_COLOR_SPACE)) {
- throw new IllegalArgumentException("Bundle does not contain a hardware bitmap");
- }
-
- HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER, HardwareBuffer.class);
- ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE,
- ParcelableColorSpace.class);
-
- return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer),
- colorSpace.getColorSpace());
- }
- }
-
private static final String TAG = "ScreenshotHelper";
// Time until we give up on the screenshot & show an error instead.
@@ -277,20 +60,35 @@
/**
* Request a screenshot be taken.
* <p>
- * Added to support reducing unit test duration; the method variant without a timeout argument
- * is recommended for general use.
+ * Convenience method for taking a full screenshot with provided source.
*
- * @param type The type of screenshot, defined by {@link ScreenshotType}
- * @param source The source of the screenshot request, defined by {@link ScreenshotSource}
- * @param handler used to process messages received from the screenshot service
+ * @param source source of the screenshot request, defined by {@link
+ * ScreenshotSource}
+ * @param handler used to process messages received from the screenshot service
* @param completionConsumer receives the URI of the captured screenshot, once saved or
- * null if no screenshot was saved
+ * null if no screenshot was saved
*/
- public void takeScreenshot(@ScreenshotType int type, @ScreenshotSource int source,
- @NonNull Handler handler, @Nullable Consumer<Uri> completionConsumer) {
- ScreenshotRequest screenshotRequest = new ScreenshotRequest(type, source);
- takeScreenshot(handler, screenshotRequest, SCREENSHOT_TIMEOUT_MS,
- completionConsumer);
+ public void takeScreenshot(@ScreenshotSource int source, @NonNull Handler handler,
+ @Nullable Consumer<Uri> completionConsumer) {
+ ScreenshotRequest request =
+ new ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, source).build();
+ takeScreenshot(request, handler, completionConsumer);
+ }
+
+ /**
+ * Request a screenshot be taken.
+ * <p>
+ *
+ * @param request description of the screenshot request, either for taking a
+ * screenshot or
+ * providing a bitmap
+ * @param handler used to process messages received from the screenshot service
+ * @param completionConsumer receives the URI of the captured screenshot, once saved or
+ * null if no screenshot was saved
+ */
+ public void takeScreenshot(ScreenshotRequest request, @NonNull Handler handler,
+ @Nullable Consumer<Uri> completionConsumer) {
+ takeScreenshotInternal(request, handler, completionConsumer, SCREENSHOT_TIMEOUT_MS);
}
/**
@@ -299,46 +97,16 @@
* Added to support reducing unit test duration; the method variant without a timeout argument
* is recommended for general use.
*
- * @param type The type of screenshot, defined by {@link ScreenshotType}
- * @param source The source of the screenshot request, defined by {@link ScreenshotSource}
- * @param handler used to process messages received from the screenshot service
- * @param timeoutMs time limit for processing, intended only for testing
+ * @param request description of the screenshot request, either for taking a
+ * screenshot or providing a bitmap
+ * @param handler used to process messages received from the screenshot service
+ * @param timeoutMs time limit for processing, intended only for testing
* @param completionConsumer receives the URI of the captured screenshot, once saved or
- * null if no screenshot was saved
+ * null if no screenshot was saved
*/
@VisibleForTesting
- public void takeScreenshot(@ScreenshotType int type, @ScreenshotSource int source,
- @NonNull Handler handler, long timeoutMs, @Nullable Consumer<Uri> completionConsumer) {
- ScreenshotRequest screenshotRequest = new ScreenshotRequest(type, source);
- takeScreenshot(handler, screenshotRequest, timeoutMs, completionConsumer);
- }
-
- /**
- * Request that provided image be handled as if it was a screenshot.
- *
- * @param screenshotBundle Bundle containing the buffer and color space of the screenshot.
- * @param boundsInScreen The bounds in screen coordinates that the bitmap originated from.
- * @param insets The insets that the image was shown with, inside the screen bounds.
- * @param taskId The taskId of the task that the screen shot was taken of.
- * @param userId The userId of user running the task provided in taskId.
- * @param topComponent The component name of the top component running in the task.
- * @param source The source of the screenshot request, defined by {@link ScreenshotSource}
- * @param handler A handler used in case the screenshot times out
- * @param completionConsumer receives the URI of the captured screenshot, once saved or
- * null if no screenshot was saved
- */
- public void provideScreenshot(@NonNull Bundle screenshotBundle, @NonNull Rect boundsInScreen,
- @NonNull Insets insets, int taskId, int userId, ComponentName topComponent,
- @ScreenshotSource int source, @NonNull Handler handler,
- @Nullable Consumer<Uri> completionConsumer) {
- ScreenshotRequest screenshotRequest = new ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE,
- source, screenshotBundle, boundsInScreen, insets, taskId, userId, topComponent);
- takeScreenshot(handler, screenshotRequest, SCREENSHOT_TIMEOUT_MS, completionConsumer);
- }
-
- private void takeScreenshot(@NonNull Handler handler,
- ScreenshotRequest screenshotRequest, long timeoutMs,
- @Nullable Consumer<Uri> completionConsumer) {
+ public void takeScreenshotInternal(ScreenshotRequest request, @NonNull Handler handler,
+ @Nullable Consumer<Uri> completionConsumer, long timeoutMs) {
synchronized (mScreenshotLock) {
final Runnable mScreenshotTimeout = () -> {
@@ -354,7 +122,7 @@
}
};
- Message msg = Message.obtain(null, 0, screenshotRequest);
+ Message msg = Message.obtain(null, 0, request);
Handler h = new Handler(handler.getLooper()) {
@Override
@@ -471,5 +239,4 @@
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT);
}
-
}
diff --git a/core/java/com/android/internal/util/ScreenshotRequest.aidl b/core/java/com/android/internal/util/ScreenshotRequest.aidl
new file mode 100644
index 0000000..b08905d
--- /dev/null
+++ b/core/java/com/android/internal/util/ScreenshotRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+parcelable ScreenshotRequest;
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/ScreenshotRequest.java b/core/java/com/android/internal/util/ScreenshotRequest.java
new file mode 100644
index 0000000..1902f80
--- /dev/null
+++ b/core/java/com/android/internal/util/ScreenshotRequest.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.os.UserHandle.USER_NULL;
+import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
+import android.graphics.Insets;
+import android.graphics.ParcelableColorSpace;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.util.Objects;
+
+/**
+ * Describes a screenshot request.
+ */
+public class ScreenshotRequest implements Parcelable {
+ private static final String TAG = "ScreenshotRequest";
+
+ @WindowManager.ScreenshotType
+ private final int mType;
+ @WindowManager.ScreenshotSource
+ private final int mSource;
+ private final ComponentName mTopComponent;
+ private final int mTaskId;
+ private final int mUserId;
+ private final Bitmap mBitmap;
+ private final Rect mBoundsInScreen;
+ private final Insets mInsets;
+
+ private ScreenshotRequest(
+ @WindowManager.ScreenshotType int type, @WindowManager.ScreenshotSource int source,
+ ComponentName topComponent, int taskId, int userId,
+ Bitmap bitmap, Rect boundsInScreen, Insets insets) {
+ mType = type;
+ mSource = source;
+ mTopComponent = topComponent;
+ mTaskId = taskId;
+ mUserId = userId;
+ mBitmap = bitmap;
+ mBoundsInScreen = boundsInScreen;
+ mInsets = insets;
+ }
+
+ ScreenshotRequest(Parcel in) {
+ mType = in.readInt();
+ mSource = in.readInt();
+ mTopComponent = in.readTypedObject(ComponentName.CREATOR);
+ mTaskId = in.readInt();
+ mUserId = in.readInt();
+ mBitmap = HardwareBitmapBundler.bundleToHardwareBitmap(in.readTypedObject(Bundle.CREATOR));
+ mBoundsInScreen = in.readTypedObject(Rect.CREATOR);
+ mInsets = in.readTypedObject(Insets.CREATOR);
+ }
+
+ @WindowManager.ScreenshotType
+ public int getType() {
+ return mType;
+ }
+
+ @WindowManager.ScreenshotSource
+ public int getSource() {
+ return mSource;
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public Rect getBoundsInScreen() {
+ return mBoundsInScreen;
+ }
+
+ public Insets getInsets() {
+ return mInsets;
+ }
+
+ public int getTaskId() {
+ return mTaskId;
+ }
+
+ public int getUserId() {
+ return mUserId;
+ }
+
+ public ComponentName getTopComponent() {
+ return mTopComponent;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeInt(mSource);
+ dest.writeTypedObject(mTopComponent, 0);
+ dest.writeInt(mTaskId);
+ dest.writeInt(mUserId);
+ dest.writeTypedObject(HardwareBitmapBundler.hardwareBitmapToBundle(mBitmap), 0);
+ dest.writeTypedObject(mBoundsInScreen, 0);
+ dest.writeTypedObject(mInsets, 0);
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<ScreenshotRequest> CREATOR =
+ new Parcelable.Creator<ScreenshotRequest>() {
+
+ @Override
+ public ScreenshotRequest createFromParcel(Parcel source) {
+ return new ScreenshotRequest(source);
+ }
+
+ @Override
+ public ScreenshotRequest[] newArray(int size) {
+ return new ScreenshotRequest[size];
+ }
+ };
+
+ /**
+ * Builder class for {@link ScreenshotRequest} objects.
+ */
+ public static class Builder {
+ @WindowManager.ScreenshotType
+ private final int mType;
+
+ @WindowManager.ScreenshotSource
+ private final int mSource;
+
+ private Bitmap mBitmap;
+ private Rect mBoundsInScreen;
+ private Insets mInsets = Insets.NONE;
+ private int mTaskId = INVALID_TASK_ID;
+ private int mUserId = USER_NULL;
+ private ComponentName mTopComponent;
+
+ /**
+ * Begin building a ScreenshotRequest.
+ *
+ * @param type The type of the screenshot request, defined by {@link
+ * WindowManager.ScreenshotType}
+ * @param source The source of the screenshot request, defined by {@link
+ * WindowManager.ScreenshotSource}
+ */
+ public Builder(
+ @WindowManager.ScreenshotType int type,
+ @WindowManager.ScreenshotSource int source) {
+ mType = type;
+ mSource = source;
+ }
+
+ /**
+ * Construct a new {@link ScreenshotRequest} with the set parameters.
+ */
+ public ScreenshotRequest build() {
+ if (mType == TAKE_SCREENSHOT_FULLSCREEN && mBitmap != null) {
+ Log.w(TAG, "Bitmap provided, but request is fullscreen. Bitmap will be ignored.");
+ }
+ if (mType == TAKE_SCREENSHOT_PROVIDED_IMAGE && mBitmap == null) {
+ throw new IllegalStateException(
+ "Request is PROVIDED_IMAGE, but no bitmap is provided!");
+ }
+
+ return new ScreenshotRequest(mType, mSource, mTopComponent, mTaskId, mUserId, mBitmap,
+ mBoundsInScreen, mInsets);
+ }
+
+ /**
+ * Set the top component associated with this request.
+ *
+ * @param topComponent The component name of the top component running in the task.
+ */
+ public Builder setTopComponent(ComponentName topComponent) {
+ mTopComponent = topComponent;
+ return this;
+ }
+
+ /**
+ * Set the task id associated with this request.
+ *
+ * @param taskId The taskId of the task that the screenshot was taken of.
+ */
+ public Builder setTaskId(int taskId) {
+ mTaskId = taskId;
+ return this;
+ }
+
+ /**
+ * Set the user id associated with this request.
+ *
+ * @param userId The userId of user running the task provided in taskId.
+ */
+ public Builder setUserId(int userId) {
+ mUserId = userId;
+ return this;
+ }
+
+ /**
+ * Set the bitmap associated with this request.
+ *
+ * @param bitmap The provided screenshot.
+ */
+ public Builder setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ return this;
+ }
+
+ /**
+ * Set the bounds for the provided bitmap.
+ *
+ * @param bounds The bounds in screen coordinates that the bitmap originated from.
+ */
+ public Builder setBoundsOnScreen(Rect bounds) {
+ mBoundsInScreen = bounds;
+ return this;
+ }
+
+ /**
+ * Set the insets for the provided bitmap.
+ *
+ * @param insets The insets that the image was shown with, inside the screen bounds.
+ */
+ public Builder setInsets(@NonNull Insets insets) {
+ mInsets = insets;
+ return this;
+ }
+ }
+
+ /**
+ * Bundler used to convert between a hardware bitmap and a bundle without copying the internal
+ * content. This is used together with a fully-defined ScreenshotRequest to handle a hardware
+ * bitmap as a screenshot.
+ */
+ private static final class HardwareBitmapBundler {
+ private static final String KEY_BUFFER = "bitmap_util_buffer";
+ private static final String KEY_COLOR_SPACE = "bitmap_util_color_space";
+
+ private HardwareBitmapBundler() {
+ }
+
+ /**
+ * Creates a Bundle that represents the given Bitmap.
+ * <p>The Bundle will contain a wrapped version of the Bitmaps HardwareBuffer, so will
+ * avoid
+ * copies when passing across processes, only pass to processes you trust.
+ *
+ * <p>Returns a new Bundle rather than modifying an exiting one to avoid key collisions,
+ * the
+ * returned Bundle should be treated as a standalone object.
+ *
+ * @param bitmap to convert to bundle
+ * @return a Bundle representing the bitmap, should only be parsed by
+ * {@link #bundleToHardwareBitmap(Bundle)}
+ */
+ private static Bundle hardwareBitmapToBundle(Bitmap bitmap) {
+ if (bitmap == null) {
+ return null;
+ }
+ if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
+ throw new IllegalArgumentException(
+ "Passed bitmap must have hardware config, found: "
+ + bitmap.getConfig());
+ }
+
+ // Bitmap assumes SRGB for null color space
+ ParcelableColorSpace colorSpace =
+ bitmap.getColorSpace() == null
+ ? new ParcelableColorSpace(ColorSpace.get(ColorSpace.Named.SRGB))
+ : new ParcelableColorSpace(bitmap.getColorSpace());
+
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(KEY_BUFFER, bitmap.getHardwareBuffer());
+ bundle.putParcelable(KEY_COLOR_SPACE, colorSpace);
+
+ return bundle;
+ }
+
+ /**
+ * Extracts the Bitmap added to a Bundle with {@link #hardwareBitmapToBundle(Bitmap)}.
+ *
+ * <p>This Bitmap contains the HardwareBuffer from the original caller, be careful
+ * passing
+ * this Bitmap on to any other source.
+ *
+ * @param bundle containing the bitmap
+ * @return a hardware Bitmap
+ */
+ private static Bitmap bundleToHardwareBitmap(Bundle bundle) {
+ if (bundle == null) {
+ return null;
+ }
+ if (!bundle.containsKey(KEY_BUFFER) || !bundle.containsKey(KEY_COLOR_SPACE)) {
+ throw new IllegalArgumentException("Bundle does not contain a hardware bitmap");
+ }
+
+ HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER, HardwareBuffer.class);
+ ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE,
+ ParcelableColorSpace.class);
+
+ return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer),
+ colorSpace.getColorSpace());
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 4cf0ba1..635adca 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -927,7 +927,8 @@
message = messages.get(i - histSize);
}
boolean isNewGroup = currentGroup == null;
- Person sender = message.getMessage().getSenderPerson();
+ Person sender =
+ message.getMessage() == null ? null : message.getMessage().getSenderPerson();
CharSequence key = getKey(sender);
isNewGroup |= !TextUtils.equals(key, currentSenderKey);
if (isNewGroup) {
@@ -1190,7 +1191,8 @@
return null;
}
final MessagingMessage messagingMessage = mMessages.get(mMessages.size() - 1);
- final CharSequence text = messagingMessage.getMessage().getText();
+ final CharSequence text = messagingMessage.getMessage() == null ? null
+ : messagingMessage.getMessage().getText();
if (text == null && messagingMessage instanceof MessagingImageMessage) {
final String unformatted =
getResources().getString(R.string.conversation_single_line_image_placeholder);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 91a5d3a..86fd956 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -77,11 +77,6 @@
private static final boolean FRP_CREDENTIAL_ENABLED = true;
/**
- * The key to identify when the lock pattern enabled flag is being accessed for legacy reasons.
- */
- public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled";
-
- /**
* The interval of the countdown for showing progress of the lockout.
*/
public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;
@@ -624,12 +619,11 @@
}
boolean disabledByDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_disableLockscreenByDefault);
- boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
UserInfo userInfo = getUserManager().getUserInfo(userId);
boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
&& userInfo.isDemo();
return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
- || (disabledByDefault && !isSystemUser)
+ || disabledByDefault
|| isDemoUser;
}
@@ -952,19 +946,6 @@
return type == CREDENTIAL_TYPE_PATTERN;
}
- @Deprecated
- public boolean isLegacyLockPatternEnabled(int userId) {
- // Note: this value should default to {@code true} to avoid any reset that might result.
- // We must use a special key to read this value, since it will by default return the value
- // based on the new logic.
- return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
- }
-
- @Deprecated
- public void setLegacyLockPatternEnabled(int userId) {
- setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
- }
-
/**
* @return Whether the visible pattern is enabled.
*/
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 146cb3f..30e4099 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -492,7 +492,9 @@
int color = mSendingSpinnerContainer.getVisibility() == View.VISIBLE
? mSendingTextColor : mTextColor;
for (MessagingMessage message : mMessages) {
- message.setColor(message.getMessage().isRemoteInputHistory() ? color : mTextColor);
+ final boolean isRemoteInputHistory =
+ message.getMessage() != null && message.getMessage().isRemoteInputHistory();
+ message.setColor(isRemoteInputHistory ? color : mTextColor);
}
}
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 67b671e..9d142f6 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -470,7 +470,8 @@
message = messages.get(i - histSize);
}
boolean isNewGroup = currentGroup == null;
- Person sender = message.getMessage().getSenderPerson();
+ Person sender =
+ message.getMessage() == null ? null : message.getMessage().getSenderPerson();
CharSequence key = sender == null ? null
: sender.getKey() == null ? sender.getName() : sender.getKey();
isNewGroup |= !TextUtils.equals(key, currentSenderKey);
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index 2cc0d23..5ecd3b8 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -68,6 +68,10 @@
default boolean sameAs(Notification.MessagingStyle.Message message) {
Notification.MessagingStyle.Message ownMessage = getMessage();
+ // We have to make sure both messages are not null to go further comparison
+ if (message == null || ownMessage == null) {
+ return message == ownMessage;
+ }
if (!Objects.equals(message.getText(), ownMessage.getText())) {
return false;
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 21f1d6d..91d2ecb 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -327,6 +327,10 @@
"libdl_android",
"libtimeinstate",
"server_configurable_flags",
+ "libimage_io",
+ "libjpegdecoder",
+ "libjpegencoder",
+ "libjpegrecoverymap",
],
export_shared_lib_headers: [
// our headers include libnativewindow's public headers
@@ -380,6 +384,10 @@
"libwebp-decode",
"libwebp-encode",
"libwuffs_mirror_release_c",
+ "libimage_io",
+ "libjpegdecoder",
+ "libjpegencoder",
+ "libjpegrecoverymap",
],
},
host_linux: {
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index a68040d..bd85874 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -72,6 +72,7 @@
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
per-file *HardwareBuffer* = file:/graphics/java/android/graphics/OWNERS
per-file android_hardware_SyncFence.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_OverlayProperties.cpp = file:/graphics/java/android/graphics/OWNERS
per-file android_os_GraphicsEnvironment.cpp = file:platform/frameworks/native:/opengl/OWNERS
### Text ###
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b60ec9f..9e92542 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -324,7 +324,7 @@
jint screen_width, jint screen_height,
jint smallest_screen_width_dp, jint screen_width_dp,
jint screen_height_dp, jint screen_layout, jint ui_mode,
- jint color_mode, jint major_version) {
+ jint color_mode, jint grammatical_gender, jint major_version) {
ATRACE_NAME("AssetManager::SetConfiguration");
ResTable_config configuration;
@@ -345,6 +345,7 @@
configuration.screenLayout = static_cast<uint8_t>(screen_layout);
configuration.uiMode = static_cast<uint8_t>(ui_mode);
configuration.colorMode = static_cast<uint8_t>(color_mode);
+ configuration.grammaticalInflection = static_cast<uint8_t>(grammatical_gender);
configuration.sdkVersion = static_cast<uint16_t>(major_version);
if (locale != nullptr) {
@@ -1448,7 +1449,7 @@
{"nativeCreate", "()J", (void*)NativeCreate},
{"nativeDestroy", "(J)V", (void*)NativeDestroy},
{"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
- {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
+ {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIIII)V",
(void*)NativeSetConfiguration},
{"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;",
(void*)NativeGetAssignedPackageIdentifiers},
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 7d379e5..0bc0878 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -68,6 +68,7 @@
}
const InputDeviceIdentifier& ident = deviceInfo.getIdentifier();
+ const auto usiVersion = deviceInfo.getUsiVersion().value_or(InputDeviceUsiVersion{-1, -1});
ScopedLocalRef<jobject>
inputDeviceObj(env,
@@ -81,7 +82,9 @@
keyboardLanguageTagObj.get(), keyboardLayoutTypeObj.get(),
deviceInfo.hasVibrator(), deviceInfo.hasMic(),
deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor(),
- deviceInfo.hasBattery(), deviceInfo.supportsUsi()));
+ deviceInfo.hasBattery(), usiVersion.majorVersion,
+ usiVersion.minorVersion,
+ deviceInfo.getAssociatedDisplayId()));
// Note: We do not populate the Bluetooth address into the InputDevice object to avoid leaking
// it to apps that do not have the Bluetooth permission.
@@ -105,7 +108,7 @@
gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
"(IIILjava/lang/String;IILjava/lang/"
"String;ZIILandroid/view/KeyCharacterMap;Ljava/"
- "lang/String;Ljava/lang/String;ZZZZZZ)V");
+ "lang/String;Ljava/lang/String;ZZZZZIII)V");
gInputDeviceClassInfo.addMotionRange =
GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "addMotionRange", "(IIFFFFF)V");
diff --git a/core/proto/android/companion/context_sync_message.proto b/core/proto/android/companion/context_sync_message.proto
new file mode 100644
index 0000000..18d25fa
--- /dev/null
+++ b/core/proto/android/companion/context_sync_message.proto
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.companion;
+
+import "frameworks/base/core/proto/android/companion/telecom.proto";
+
+option java_multiple_files = true;
+
+// Next index: 5
+message ContextSyncMessage {
+ int32 version = 1;
+ // Media data and invitations data omitted.
+ reserved 2, 3;
+ // The current telecom snapshot.
+ Telecom telecom = 4;
+}
diff --git a/core/proto/android/companion/telecom.proto b/core/proto/android/companion/telecom.proto
new file mode 100644
index 0000000..9ccadbf
--- /dev/null
+++ b/core/proto/android/companion/telecom.proto
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+syntax = "proto3";
+
+package android.companion;
+
+option java_multiple_files = true;
+
+// Next index: 2
+message Telecom {
+ // Next index: 5
+ message Call {
+ // UUID representing this call
+ int64 id = 1;
+
+ message Origin {
+ // Caller's name and/or phone number; what a user would see displayed when receiving an
+ // incoming call on the local device
+ string caller_id = 1;
+ // Human-readable name of the app processing this call
+ string app_name = 2;
+ bytes app_icon = 3;
+ }
+ Origin origin = 2;
+
+ enum Status {
+ UNKNOWN_STATUS = 0;
+ RINGING = 1;
+ ONGOING = 2;
+ ON_HOLD = 3;
+ RINGING_SILENCED = 4;
+ }
+ Status status = 3;
+
+ enum Control {
+ UNKNOWN_CONTROL = 0;
+ ACCEPT = 1;
+ REJECT = 2;
+ SILENCE = 3;
+ MUTE = 4;
+ UNMUTE = 5;
+ END = 6;
+ PUT_ON_HOLD = 7;
+ TAKE_OFF_HOLD = 8;
+ REJECT_AND_BLOCK = 9;
+ IGNORE = 10;
+ }
+ repeated Control controls_available = 4;
+ }
+
+ // The list of active calls.
+ repeated Call calls = 1;
+}
diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto
index b1ffe38..0e2234f 100644
--- a/core/proto/android/content/configuration.proto
+++ b/core/proto/android/content/configuration.proto
@@ -50,6 +50,7 @@
optional .android.app.WindowConfigurationProto window_configuration = 19;
optional string locale_list = 20;
optional uint32 font_weight_adjustment = 21;
+ optional uint32 grammatical_gender = 22;
}
/**
diff --git a/core/proto/android/nfc/nfc_service.proto b/core/proto/android/nfc/nfc_service.proto
index 1dcd5cc..2df1d5d 100644
--- a/core/proto/android/nfc/nfc_service.proto
+++ b/core/proto/android/nfc/nfc_service.proto
@@ -60,7 +60,7 @@
optional bool secure_nfc_capable = 13;
optional bool vr_mode_enabled = 14;
optional DiscoveryParamsProto discovery_params = 15;
- reserved 16;
+ optional P2pLinkManagerProto p2p_link_manager = 16;
optional com.android.nfc.cardemulation.CardEmulationManagerProto card_emulation_manager = 17;
optional NfcDispatcherProto nfc_dispatcher = 18;
optional string native_crash_logs = 19 [(.android.privacy).dest = DEST_EXPLICIT];
@@ -77,6 +77,38 @@
optional bool enable_p2p = 5;
}
+// Debugging information for com.android.nfc.P2pLinkManager
+message P2pLinkManagerProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ enum LinkState {
+ LINK_STATE_UNKNOWN = 0;
+ LINK_STATE_DOWN = 1;
+ LINK_STATE_DEBOUNCE = 2;
+ LINK_STATE_UP = 3;
+ }
+
+ enum SendState {
+ SEND_STATE_UNKNOWN = 0;
+ SEND_STATE_NOTHING_TO_SEND = 1;
+ SEND_STATE_NEED_CONFIRMATION = 2;
+ SEND_STATE_SENDING = 3;
+ SEND_STATE_COMPLETE = 4;
+ SEND_STATE_CANCELED = 5;
+ }
+
+ optional int32 default_miu = 1;
+ optional int32 default_rw_size = 2;
+ optional LinkState link_state = 3;
+ optional SendState send_state = 4;
+ optional int32 send_flags = 5;
+ optional bool send_enabled = 6;
+ optional bool receive_enabled = 7;
+ optional string callback_ndef = 8 [(.android.privacy).dest = DEST_EXPLICIT];
+ optional .android.nfc.NdefMessageProto message_to_send = 9;
+ repeated string uris_to_send = 10 [(.android.privacy).dest = DEST_EXPLICIT];
+}
+
// Debugging information for com.android.nfc.NfcDispatcher
message NfcDispatcherProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index e165b07..fd0d9c5 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -160,7 +160,7 @@
optional Bluetooth bluetooth = 21;
optional SettingProto boot_count = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto bugreport_in_power_menu = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 23; // Moved to secure settings bugreport_in_power_menu
optional SettingProto cached_apps_freezer_enabled = 152 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto call_auto_retry = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index e6f942e..ea0ec79 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -186,6 +186,7 @@
optional Backup backup = 10;
optional SettingProto bluetooth_on_while_driving = 11 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto bugreport_in_power_menu = 95 [ (android.privacy).dest = DEST_AUTOMATIC ];
message Camera {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -696,5 +697,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 95;
+ // Next tag = 96;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3f18e5a..bc40cef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6487,6 +6487,7 @@
<!-- Allows a regular application to use {@link android.app.Service#startForeground
Service.startForeground} with the type "fileManagement".
<p>Protection level: normal|instant
+ @hide
-->
<permission android:name="android.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT"
android:description="@string/permdesc_foregroundServiceFileManagement"
@@ -7040,6 +7041,28 @@
android:protectionLevel="signature|knownSigner"
android:knownCerts="@array/config_healthConnectMigrationKnownSigners" />
+ <!-- @SystemApi Allows an app to query apps in clone profile. The permission is
+ bidirectional in nature, i.e. cloned apps would be able to query apps in root user.
+ The permission is not meant for 3P apps as of now.
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.QUERY_CLONED_APPS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @SystemApi
+ Allows applications to capture bugreport directly without consent dialog when using the
+ bugreporting API on userdebug/eng build.
+ <p>The application still needs to hold {@link android.permission.DUMP} permission and be
+ bugreport-whitelisted to be able to capture a bugreport using the bugreporting API in the
+ first place. Then, when the corresponding app op of this permission is ALLOWED, the
+ bugreport can be captured directly without going through the consent dialog.
+ <p>Protection level: internal|appop
+ <p>Intended to only be used on userdebug/eng build.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD"
+ android:protectionLevel="internal|appop" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/core/res/res/drawable/pointer_handwriting_icon.xml b/core/res/res/drawable/pointer_handwriting_icon.xml
new file mode 100644
index 0000000..cdbf693
--- /dev/null
+++ b/core/res/res/drawable/pointer_handwriting_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+ android:bitmap="@drawable/pointer_crosshair"
+ android:hotSpotX="12dp"
+ android:hotSpotY="12dp" />
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 48614ed..8c1b6ed 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Kleurregstelling"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Eenhandmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra donker"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Gehoortoestelle"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Druk en hou albei volumesleutels drie sekondes lank om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruik"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Skakel werkprogramme aan?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Kry toegang tot jou werkprogramme en -kennisgewings"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Skakel aan"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Program is nie beskikbaar nie"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is nie op die oomblik beskikbaar nie."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> is nie beskikbaar nie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 3843df9..708b9fd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"የቀለም ማስተካከያ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"የአንድ እጅ ሁነታ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ተጨማሪ ደብዛዛ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"የመስሚያ መሣሪያዎች"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ጠፍተዋል።"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን ለመጠቀም ለሦስት ሰከንዶች ሁለቱንም የድምፅ ቁልፎች ተጭነው ይያዙ"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"የሥራ መተግበሪያዎች ይብሩ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"የእርስዎን የሥራ መተግበሪያዎች እና ማሳወቂያዎች መዳረሻ ያግኙ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"አብራ"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"መተግበሪያ አይገኝም"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን አይገኝም።"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> አይገኝም"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 3514ff1..e524fc7 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1712,6 +1712,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"تصحيح الألوان"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"وضع \"التصفح بيد واحدة\""</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"زيادة تعتيم الشاشة"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعات الأذن الطبية"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"اضغط مع الاستمرار على مفتاحي مستوى الصوت لمدة 3 ثوانٍ لاستخدام <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1946,6 +1947,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"هل تريد تفعيل تطبيقات العمل؟"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"الوصول إلى تطبيقات العمل وإشعاراتها"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"تفعيل"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"التطبيق غير متاح"</string>
<string name="app_blocked_message" msgid="542972921087873023">"تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> غير متاح الآن."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"تطبيق <xliff:g id="ACTIVITY">%1$s</xliff:g> غير متاح"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 234534a..5409045 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ৰং শুধৰণী"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এখন হাতেৰে ব্যৱহাৰ কৰাৰ ম’ড"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"এক্সট্ৰা ডিম"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"শুনাৰ ডিভাইচ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবলৈ দুয়োটা ভলিউম বুটাম তিনি ছেকেণ্ডৰ বাবে হেঁচি ৰাখক"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"কৰ্মস্থানৰ এপ্ অন কৰিবনে?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"আপোনাৰ কৰ্মস্থানৰ এপ্ আৰু জাননীৰ এক্সেছ পাওক"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"অন কৰক"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"এপ্টো উপলব্ধ নহয়"</string>
<string name="app_blocked_message" msgid="542972921087873023">"এই মুহূৰ্তত <xliff:g id="APP_NAME">%1$s</xliff:g> উপলব্ধ নহয়।"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলব্ধ নহয়"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f35da2d..efa6c67 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Rəng korreksiyası"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Birəlli rejim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Əlavə tündləşmə"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eşitmə cihazları"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> istifadə etmək üçün hər iki səs düyməsini üç saniyə basıb saxlayın"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"İş tətbiqləri aktiv edilsin?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"İş tətbiqlərinizə və bildirişlərinizə giriş əldə edin"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivləşdirin"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Tətbiq əlçatan deyil"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hazırda əlçatan deyil."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> əlçatan deyil"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index d849bb0..0677369 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcija boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite oba tastera za jačinu zvuka tri sekunde da biste koristili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Uključujete poslovne aplikacije?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pristupajte poslovnim aplikacijama i obaveštenjima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 970fac3..07cdb89 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Карэкцыя колераў"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Рэжым кіравання адной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дадатковае памяншэнне яркасці"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слыхавыя апараты"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Каб карыстацца сэрвісам \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", націсніце і ўтрымлівайце на працягу трох секунд абедзве клавішы гучнасці"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Уключыць працоўныя праграмы?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Атрымаць доступ да працоўных праграм і апавяшчэнняў"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Уключыць"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Праграма недаступная"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" цяпер недаступная."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недаступна: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c37ed33..4139e95 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекция на цветове"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Работа с една ръка"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Доп. затъмн."</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухови апарати"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"За да използвате <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натиснете двата бутона за силата на звука и ги задръжте за 3 секунди"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Включване на служ. приложения?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Получете достъп до служебните си приложения и известия"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Включване"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Приложението не е достъпно"</string>
<string name="app_blocked_message" msgid="542972921087873023">"В момента няма достъп до <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> не е налице"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index ec1ef28..09e592c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"রঙ সংশোধন করা"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এক হাতে ব্যবহার করার মোড"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম আলো"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"হিয়ারিং ডিভাইস"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ব্যবহার করতে ভলিউম কী বোতাম ৩ সেকেন্ডের জন্য চেপে ধরে রাখুন"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"অফিস অ্যাপ চালু করবেন?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"আপনার অফিস অ্যাপ এবং বিজ্ঞপ্তিতে অ্যাক্সেস পান"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"চালু করুন"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"অ্যাপ পাওয়া যাচ্ছে না"</string>
<string name="app_blocked_message" msgid="542972921087873023">"এই মুহূর্তে <xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপ পাওয়া যাচ্ছে না।"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> উপলভ্য নেই"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index db572e0..4bc3399 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ispravka boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjeno"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite obje tipke za podešavanje jačine zvuka i držite ih pritisnutim tri sekunde da koristite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pristupite poslovnim aplikacijama i obavještenjima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno nije dostupna."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Nedostupno: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b5e2c76..b863fb5 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correcció de color"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode d\'una mà"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuació extra"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audiòfons"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premudes les dues tecles de volum durant 3 segons per fer servir <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Activar aplicacions de treball?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Accedeix a les teves aplicacions i notificacions de treball"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activa"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"L\'aplicació no està disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Ara mateix, <xliff:g id="APP_NAME">%1$s</xliff:g> no està disponible."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no està disponible"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7fe373f..10b92c8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekce barev"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jedné ruky"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Velmi tmavé"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Naslouchátka"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Chcete-li používat službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tři sekundy podržte stisknutá obě tlačítka hlasitosti"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Zapnout pracovní aplikace?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Získejte přístup ke svým pracovním aplikacím a oznámením"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnout"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikace není k dispozici"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> v tuto chvíli není k dispozici."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> není k dispozici"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 715349d..cae119d 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Farvekorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndstilstand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dæmpet belysning"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Hold begge lydstyrkeknapper nede i tre sekunder for at bruge <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vil du aktivere arbejdsapps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Få adgang til dine arbejdsapps og notifikationer"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Slå til"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Appen er ikke tilgængelig"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgængelig lige nu."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er ikke understøttet"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6733faa..8d0d56a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Farbkorrektur"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhandmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradunkel"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörgeräte"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Geschäftliche Apps aktivieren?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Du erhältst Zugriff auf deine geschäftlichen Apps und Benachrichtigungen"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivieren"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"App ist nicht verfügbar"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ist derzeit nicht verfügbar."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nicht verfügbar"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5c57f95..effa751 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Διόρθωση χρωμάτων"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Λειτουργία ενός χεριού"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Επιπλέον μείωση φωτεινότητας"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Συσκευές ακοής"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Πατήστε παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα, ώστε να χρησιμοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ενεργοπ. εφαρμογών εργασιών;"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Αποκτήστε πρόσβαση στις εφαρμογές εργασιών και τις ειδοποιήσεις"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ενεργοποίηση"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Η εφαρμογή δεν είναι διαθέσιμη"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν είναι διαθέσιμη αυτήν τη στιγμή."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> δεν διατίθεται"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 4e26ec2..a83ae5c 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Colour correction"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Turn on work apps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Get access to your work apps and notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 5e5256c..599d6fc 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Color correction"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Handed mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,8 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Turn on work apps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Get access to your work apps and notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
+ <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Emergency"</string>
+ <string name="work_mode_dialer_off_message" msgid="2193299184850387465">"Get access to your work apps and calls"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 6600a4f..c691bb2 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Colour correction"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Turn on work apps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Get access to your work apps and notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 34438a5..7ec6567 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Colour correction"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Turn on work apps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Get access to your work apps and notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 02744a6..b18ee98 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Color correction"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Handed mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Press and hold both volume keys for three seconds to use <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,8 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Turn on work apps?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Get access to your work apps and notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Turn on"</string>
+ <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Emergency"</string>
+ <string name="work_mode_dialer_off_message" msgid="2193299184850387465">"Get access to your work apps and calls"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"App is not available"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is not available right now."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> unavailable"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2920b20..22ccd22 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección de colores"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo de una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se presionaron las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén presionadas ambas teclas de volumen durante tres segundos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"¿Activar apps de trabajo?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Obtén acceso a tus apps de trabajo y notificaciones"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"La app no está disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible en este momento."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 7ab1057..f1f43cd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección de color"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo Una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener pulsadas las teclas de volumen, se ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se han mantenido pulsadas las teclas de volumen. Se ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Para utilizar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas ambas teclas de volumen durante 3 segundos"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"¿Activar aplicaciones de trabajo?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Accede a tus aplicaciones y notificaciones de trabajo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"La aplicación no está disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"En estos momentos, <xliff:g id="APP_NAME">%1$s</xliff:g> no está disponible."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> no disponible"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index a3b11db..bb969ad 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Värvide korrigeerimine"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ühekäerežiim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Eriti tume"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuuldeseadmed"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kasutamiseks hoidke kolm sekundit all mõlemat helitugevuse klahvi"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Lülitada töörakendused sisse?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Hankige juurdepääs oma töörakendustele ja märguannetele"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Lülita sisse"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Rakendus ei ole saadaval"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole praegu saadaval."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei ole saadaval"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 32778f0..78a5398 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -75,7 +75,7 @@
<string name="CLIRPermanent" msgid="166443681876381118">"Ezin duzu aldatu deitzailearen identitatearen ezarpena."</string>
<string name="auto_data_switch_title" msgid="3286350716870518297">"<xliff:g id="CARRIERDISPLAY">%s</xliff:g> operadorearen datu-konexiora aldatu zara"</string>
<string name="auto_data_switch_content" msgid="803557715007110959">"Ezarpenak atalean alda dezakezu aukera hori"</string>
- <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Ez dago mugikorreko datu-zerbitzurik"</string>
+ <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Ez dago mugikorretarako datu-zerbitzurik"</string>
<string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"Ezin da egin larrialdi-deirik"</string>
<string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"Ez dago ahots-deien zerbitzurik"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"Ez dago ahozko zerbitzurik eta ezin da egin larrialdi-deirik"</string>
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Koloreen zuzenketa"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Esku bakarreko modua"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Are ilunago"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audifonoak"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> erabiltzeko, eduki sakatuta bi bolumen-botoiak hiru segundoz"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Laneko aplikazioak aktibatu nahi dituzu?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Atzitu laneko aplikazioak eta jakinarazpenak"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktibatu"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikazioa ez dago erabilgarri"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ez dago erabilgarri une honetan."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ez dago erabilgarri"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 1bdba0b..9721cfc 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"تصحیح رنگ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"حالت یکدستی"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"بسیار کمنور"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"دستگاههای کمکشنوایی"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"برای استفاده از <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید صدا را فشار دهید و سه ثانیه نگه دارید"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"برنامههای کاری روشن شود؟"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"دسترسی به اعلانها و برنامههای کاری"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"روشن کردن"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"برنامه در دسترس نیست"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحالحاضر در دسترس نیست."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دردسترس نیست"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 43f4172..a4b3568 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Värinkorjaus"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Yhden käden moodi"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Erittäin himmeä"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuulolaitteet"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Voit käyttää palvelua <xliff:g id="SERVICE_NAME">%1$s</xliff:g> painamalla molempia äänenvoimakkuuspainikkeita kolmen sekunnin ajan"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Käytetäänkö työsovelluksia?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Palauta työsovellukset ja ilmoitukset käyttöön"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ota käyttöön"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Sovellus ei ole käytettävissä"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei ole nyt käytettävissä."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ei käytettävissä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 31c96f1..8cc239e 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correction des couleurs"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode Une main"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Très sombre"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Appareils auditifs"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez les deux touches de volume enfoncées pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Activer applis professionnelles?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Accédez à vos applications professionnelles et à vos notifications"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"L\'application n\'est pas accessible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas accessible pour le moment."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non accessible"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index dc3e503..db14f84 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correction des couleurs"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode une main"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Encore moins lumineux"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Prothèses auditives"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Appuyez de manière prolongée sur les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Activer les applis pro ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Accéder à vos applis et notifications professionnelles"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activer"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Application non disponible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas disponible pour le moment."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponible"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 1d014737..e655e69 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corrección da cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo dunha soa man"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Mantén premidas as teclas do volume durante tres segudos para usar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Activar as apps do traballo?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Obtén acceso ás túas aplicacións e notificacións do traballo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"A aplicación non está dispoñible"</string>
<string name="app_blocked_message" msgid="542972921087873023">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> non está dispoñible neste momento."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non está dispoñible"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 76fb45f..feb3e9f 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"રંગ સુધારણા"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"એક-હાથે વાપરો મોડ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"એક્સ્ટ્રા ડિમ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"સાંભળવામાં સહાય કરતા ડિવાઇસ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>નો ઉપયોગ કરવા માટે બન્ને વૉલ્યૂમ કીને ત્રણ સેકન્ડ સુધી દબાવી રાખો"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"શું ઑફિસ માટેની ઍપ ચાલુ કરીએ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"તમારી ઑફિસ માટેની ઍપ અને નોટિફિકેશનનો ઍક્સેસ મેળવો"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ચાલુ કરો"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ઍપ ઉપલબ્ધ નથી"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> હાલમાં ઉપલબ્ધ નથી."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ઉપલબ્ધ નથી"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 155f254..c6d26a2 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"रंग में सुधार करने की सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"वन-हैंडेड मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"सुनने में मदद करने वाले डिवाइस"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> इस्तेमाल करने के लिए आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ऑफ़िस के काम से जुड़े ऐप्लिकेशन चालू करने हैं?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"अपने ऑफ़िस के काम से जुड़े ऐप्लिकेशन और सूचनाओं का ऐक्सेस पाएं"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"चालू करें"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ऐप्लिकेशन उपलब्ध नहीं है"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> इस समय उपलब्ध नहीं है."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नहीं है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7de0b31..b1a6153 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcija boja"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Još tamnije"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni uređaji"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pritisnite i zadržite tipke za glasnoću na tri sekunde da biste koristili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Uključiti poslovne aplikacije?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pristupite svojim poslovnim aplikacijama i obavijestima"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Uključi"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija nije dostupna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutačno nije dostupna."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – nije dostupno"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 955739f..951336c 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Színjavítás"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Egykezes mód"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extrasötét"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hallásjavító eszközök"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> használatához tartsa lenyomva három másodpercig a két hangerőgombot"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Bekapcsolja a munkaappokat?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Hozzáférést kaphat munkahelyi alkalmazásaihoz és értesítéseihez"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Bekapcsolás"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Az alkalmazás nem hozzáférhető"</string>
<string name="app_blocked_message" msgid="542972921087873023">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> jelenleg nem hozzáférhető."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"A(z) <xliff:g id="ACTIVITY">%1$s</xliff:g> nem áll rendelkezése"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 3a96b70..29c1121 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Գունաշտկում"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Մեկ ձեռքի ռեժիմ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Հավելյալ խամրեցում"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Լսողական սարքեր"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"«<xliff:g id="SERVICE_NAME">%1$s</xliff:g>» ծառայությունն օգտագործելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակները"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Միացնե՞լ հավելվածները"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Ձեզ հասանելի կդառնան ձեր աշխատանքային հավելվածներն ու ծանուցումները"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Միացնել"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Հավելվածը հասանելի չէ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն այս պահին հասանելի չէ։"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 20e7f9a..d09926d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Koreksi warna"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode satu tangan"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra redup"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Alat bantu dengar"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua tombol volume selama tiga detik untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Aktifkan aplikasi kerja?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Dapatkan akses ke aplikasi kerja dan notifikasi"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktifkan"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikasi tidak tersedia"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia saat ini."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index e230406..0057e19 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1708,6 +1708,8 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Litaleiðrétting"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhent stilling"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mjög dökkt"</string>
+ <!-- no translation found for hearing_aids_feature_name (1125892105105852542) -->
+ <skip />
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Haltu báðum hljóðstyrkstökkunum inni í þrjár sekúndur til að nota <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Kveikja á vinnuforritum?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Fá aðgang að vinnuforritum og tilkynningum"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Kveikja"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Forrit er ekki tiltækt"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ekki tiltækt núna."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ekki í boði"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3537519..4ba4b29 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correzione del colore"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modalità a una mano"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Attenuazione extra"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Apparecchi acustici"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tieni premuti entrambi i tasti del volume per tre secondi per utilizzare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Attivare le app di lavoro?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Attiva l\'accesso alle app di lavoro e alle notifiche"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Attiva"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"L\'app non è disponibile"</string>
<string name="app_blocked_message" msgid="542972921087873023">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> non è al momento disponibile."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> non disponibile"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 2dd23ac..7bb43b0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"תיקון צבע"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"מצב שימוש ביד אחת"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"מעומעם במיוחד"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"מכשירי שמיעה"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"יש ללחוץ לחיצה ארוכה על שני לחצני עוצמת הקול למשך שלוש שניות כדי להשתמש בשירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"להפעיל את האפליקציות לעבודה?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"קבלת גישה להתראות ולאפליקציות בפרופיל העבודה"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"הפעלה"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"האפליקציה לא זמינה"</string>
<string name="app_blocked_message" msgid="542972921087873023">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא זמינה בשלב זה."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> לא זמינה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 8f618c5..79bd6cb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"色補正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"片手モード"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"さらに輝度を下げる"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"補聴器"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を使用するには、音量大と音量小の両方のボタンを 3 秒間長押ししてください"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"仕事用アプリを ON にしますか?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"仕事用のアプリを利用し、通知を受け取れるようになります"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ON にする"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"アプリの利用不可"</string>
<string name="app_blocked_message" msgid="542972921087873023">"現在 <xliff:g id="APP_NAME">%1$s</xliff:g> はご利用になれません。"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>は利用できません"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 2060c83..f173973 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ფერთა კორექცია"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ცალი ხელის რეჟიმი"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"დამატებითი დაბინდვა"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"სმენის აპარატები"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> რომ გამოიყენოთ, დააჭირეთ ხმის ორივე ღილაკზე 3 წამის განმავლობაში"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"გსურთ სამსახურის აპების ჩართვა?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"თქვენი სამსახურის აპებსა და შეტყობინებებზე წვდომის მოპოვება"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ჩართვა"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"აპი მიუწვდომელია"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ამჟამად მიუწვდომელია."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> მიუწვდომელია"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 9015e1a..b8aa264 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Түсті түзету"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бір қолмен басқару режимі"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Экранды қарайту"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Есту аппараттары"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін пайдалану үшін дыбыс деңгейін реттейтін екі түймені де 3 секунд басып тұрыңыз"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Жұмыс қолданбаларын қосасыз ба?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Жұмыс қолданбалары мен хабарландыруларына қол жеткізесіз."</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Қосу"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Қолданба қолжетімді емес"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> қазір қолжетімді емес."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> қолжетімсіз"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 1a8508f..44b6137 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ការកែតម្រូវពណ៌"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"មុខងារប្រើដៃម្ខាង"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ពន្លឺតិចខ្លាំង"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ឧបករណ៍ស្តាប់"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ចុចគ្រាប់ចុចកម្រិតសំឡេងទាំងពីរឱ្យជាប់រយៈពេលបីវិនាទី ដើម្បីប្រើ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"បើកកម្មវិធីការងារឬ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ទទួលបានសិទ្ធិចូលប្រើការជូនដំណឹង និងកម្មវិធីការងាររបស់អ្នក"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"បើក"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"មិនអាចប្រើកម្មវិធីនេះបានទេ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"មិនអាចប្រើ <xliff:g id="APP_NAME">%1$s</xliff:g> នៅពេលនេះបានទេ។"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"មិនអាចប្រើ <xliff:g id="ACTIVITY">%1$s</xliff:g> បានទេ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 3d8301c..1e2a5fa 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ಒಂದು ಕೈ ಮೋಡ್"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ಇನ್ನಷ್ಟು ಮಬ್ಬು"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸಲು ಎರಡೂ ಧ್ವನಿ ಕೀಗಳನ್ನು ಮೂರು ಸೆಕೆಂಡ್ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ಕೆಲಸ ಆ್ಯಪ್ಗಳನ್ನು ಆನ್ ಮಾಡಬೇಕೆ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ನಿಮ್ಮ ಕೆಲಸಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಆ್ಯಪ್ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಪಡೆಯಿರಿ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ಆನ್ ಮಾಡಿ"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ಆ್ಯಪ್ ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಇದೀಗ ಲಭ್ಯವಿಲ್ಲ."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3448b36..dbcf849 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"색상 보정"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"한 손 모드"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"더 어둡게"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"보청기"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 서비스를 사용하려면 두 볼륨 키를 3초 동안 길게 누르세요"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"직장 앱을 사용 설정하시겠습니까?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"직장 앱 및 알림에 액세스하세요."</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"사용 설정"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"앱을 사용할 수 없습니다"</string>
<string name="app_blocked_message" msgid="542972921087873023">"현재 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱을 사용할 수 없습니다."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> 사용할 수 없음"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 7168a60..edb0886 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -261,7 +261,7 @@
<string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"Учак режими"</string>
<string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"Учак режими КҮЙҮК"</string>
<string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"Учак режими ӨЧҮК"</string>
- <string name="global_action_settings" msgid="4671878836947494217">"Жөндөөлөр"</string>
+ <string name="global_action_settings" msgid="4671878836947494217">"Параметрлер"</string>
<string name="global_action_assist" msgid="2517047220311505805">"Жардам"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"Үн жардамчысы"</string>
<string name="global_action_lockdown" msgid="2475471405907902963">"Бекем кулпулоо"</string>
@@ -663,7 +663,7 @@
<string name="face_recalibrate_notification_content" msgid="3064513770251355594">"Жүзүңүздүн үлгүсүн өчүрүү үчүн басып, жаңы үлгүнү кошуңуз"</string>
<string name="face_setup_notification_title" msgid="8843461561970741790">"Жүзүнөн таанып ачууну тууралоо"</string>
<string name="face_setup_notification_content" msgid="5463999831057751676">"Телефонуңузду карап туруп эле кулпусун ачып алыңыз"</string>
- <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Жүзүнөн таанып ачуу функциясын колдонуу үчүн Жөндөөлөр > Купуялык бөлүмүнө өтүп, "<b>"Камераны колдонууну"</b>" күйгүзүңүз"</string>
+ <string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Жүзүнөн таанып ачуу функциясын колдонуу үчүн Параметрлер > Купуялык бөлүмүнө өтүп, "<b>"Камераны колдонууну"</b>" күйгүзүңүз"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Кулпусун ачуунун көбүрөөк жолдорун жөндөңүз"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Манжа изин кошуу үчүн басыңыз"</string>
<string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Кулпуланган түзмөктү манжа изи менен ачуу"</string>
@@ -1621,7 +1621,7 @@
<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_searching" msgid="6119673534251329535">"Түзмөктөр изделүүдө..."</string>
- <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"Жөндөөлөр"</string>
+ <string name="media_route_chooser_extended_settings" msgid="2506352159381327741">"Параметрлер"</string>
<string name="media_route_controller_disconnect" msgid="7362617572732576959">"Ажыратуу"</string>
<string name="media_route_status_scanning" msgid="8045156315309594482">"Скандоодо..."</string>
<string name="media_route_status_connecting" msgid="5845597961412010540">"Туташууда..."</string>
@@ -1680,10 +1680,10 @@
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең 3 секунддай коё бербей басып туруңуз."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Атайын мүмкүнчүлүктөрдүн ыкчам баскычын иштетесизби?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн үндү катуулатуу/акырындатуу баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Атайын мүмкүнчүлүктөр функциясын иштетүү үчүн үндү катуулатуу/акырындатуу баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nУчурдагы функциялар:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nТандалган функцияларды өзгөртүү үчүн Параметрлер > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="2128323171922023762">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> ыкчам баскычын иштетесизби?"</string>
- <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн үндү катуулатуу/акырындатуу баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Жөндөөлөр > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
+ <string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"<xliff:g id="SERVICE">%1$s</xliff:g> кызматын иштетүү үчүн үндү катуулатуу/акырындатуу баскычтарын бир нече секунд коё бербей басып туруңуз. Ушуну менен, түзмөгүңүз бир аз башкача иштеп калышы мүмкүн.\n\nБаскычтардын ушул айкалышын башка функцияга дайындоо үчүн, Параметрлер > Атайын мүмкүнчүлүктөр бөлүмүнө өтүңүз."</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"Ооба"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"Жок"</string>
<string name="accessibility_shortcut_menu_item_status_on" msgid="6608392117189732543">"КҮЙҮК"</string>
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Түстөрдү тууралоо"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бир кол режими"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Кошумча караңгылатуу"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Угуу түзмөктөрү"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын колдонуу үчүн үнүн чоңойтуп/кичирейтүү баскычтарын үч секунд коё бербей басып туруңуз"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Жумуш колдонмолору күйгүзүлсүнбү?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Жумуш колдонмолоруңузга жана билдирмелериңизге мүмкүнчүлүк алыңыз"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Күйгүзүү"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Колдонмо учурда жеткиликсиз"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> учурда жеткиликсиз"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> жеткиликсиз"</string>
@@ -2066,7 +2071,7 @@
<string name="review_notification_settings_remind_me_action" msgid="1081081018678480907">"Кийинчерээк эскертүү"</string>
<string name="review_notification_settings_dismiss" msgid="4160916504616428294">"Жабуу"</string>
<string name="notification_app_name_system" msgid="3045196791746735601">"Тутум"</string>
- <string name="notification_app_name_settings" msgid="9088548800899952531">"Жөндөөлөр"</string>
+ <string name="notification_app_name_settings" msgid="9088548800899952531">"Параметрлер"</string>
<string name="notification_appops_camera_active" msgid="8177643089272352083">"Камера"</string>
<string name="notification_appops_microphone_active" msgid="581333393214739332">"Микрофон"</string>
<string name="notification_appops_overlay_active" msgid="5571732753262836481">"экрандагы башка терезелердин үстүнөн көрсөтүлүүдө"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index e5b4b45..1874d27 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ການແກ້ໄຂສີ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ໂໝດມືດຽວ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ຫຼຸດແສງເປັນພິເສດ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ອຸປະກອນຊ່ວຍຟັງ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"ກົດປຸ່ມສຽງທັງສອງພ້ອມກັນຄ້າງໄວ້ສາມວິນາທີເພື່ອໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ເປີດໃຊ້ແອັບບ່ອນເຮັດວຽກບໍ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ຮັບສິດເຂົ້າເຖິງແອັບບ່ອນເຮັດວຽກ ແລະ ການແຈ້ງເຕືອນຂອງທ່ານ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ເປີດ"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ແອັບບໍ່ສາມາດໃຊ້ໄດ້"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ສາມາດໃຊ້ໄດ້ໃນຕອນນີ້."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"ບໍ່ສາມາດໃຊ້ <xliff:g id="ACTIVITY">%1$s</xliff:g> ໄດ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7292bbb..b0c481e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Spalvų taisymas"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienos rankos režimas"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Itin blanku"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Klausos įrenginiai"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Jei norite naudoti „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite abu garsumo klavišus ir palaikykite tris sekundes"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Įjungti darbo programas?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pasiekite darbo programas ir pranešimus"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Įjungti"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Programa nepasiekiama."</string>
<string name="app_blocked_message" msgid="542972921087873023">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ šiuo metu nepasiekiama."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"„<xliff:g id="ACTIVITY">%1$s</xliff:g>“ nepasiekiama"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5a5d70e..3aca9f8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Krāsu korekcija"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienas rokas režīms"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Papildu aptumšošana"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dzirdes aparāti"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Lai izmantotu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, nospiediet abus skaļuma pogas un turiet tos trīs sekundes."</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vai ieslēgt darba lietotnes?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Iegūstiet piekļuvi darba lietotnēm un paziņojumiem"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ieslēgt"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Lietotne nav pieejama"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pašlaik nav pieejama."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nav pieejams"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 9826e9a..28d5969 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекција на боите"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим со една рака"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнително затемнување"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни помагала"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притиснете ги и задржете ги двете копчиња за јачина на звукот во траење од три секунди за да користите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Да се вклучат работни апликации?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Добијте пристап до вашите работни апликации и известувања"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Вклучи"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Апликацијата не е достапна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> не е достапна во моментов."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> е недостапна"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index cf65fdd..4076c68 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"നിറം ശരിയാക്കൽ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ഒറ്റക്കൈ മോഡ്"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"കൂടുതൽ ഡിം ചെയ്യൽ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ശ്രവണ ഉപകരണങ്ങൾ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഉപയോഗിക്കാൻ, രണ്ട് വോളിയം കീകളും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ഔദ്യോഗിക ആപ്പുകൾ ഓണാക്കണോ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"നിങ്ങളുടെ ഔദ്യോഗിക ആപ്പുകളിലേക്കും അറിയിപ്പുകളിലേക്കും ആക്സസ് നേടുക"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ഓണാക്കുക"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ആപ്പ് ലഭ്യമല്ല"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ഇപ്പോൾ ലഭ്യമല്ല."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ലഭ്യമല്ല"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index bbfff4a..28fa200 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Өнгөний засвар"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Нэг гарын горим"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Хэт бүүдгэр"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Сонсголын төхөөрөмжүүд"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г ашиглахын тулд дууны түвшнийг ихэсгэх, багасгах түлхүүрийг 3 секундийн турш зэрэг дарна уу"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ажлын аппуудыг асаах уу?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Ажлын аппууд болон мэдэгдлүүддээ хандах эрх аваарай"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Асаах"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Апп боломжгүй байна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> яг одоо боломжгүй байна."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> боломжгүй байна"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 06bb79f..d0d9da3 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"रंग सुधारणा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एकहाती मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"आणखी डिम"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"श्रवणयंत्र डिव्हाइस"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> वापरण्यासाठी दोन्ही व्हॉल्युम की तीन सेकंद दाबा आणि धरून ठेवा"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"कार्य अॅप्स सुरू करायची का?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"तुमची कार्य ॲप्स आणि सूचना यांचा अॅक्सेस मिळवा"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"सुरू करा"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ॲप उपलब्ध नाही"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> आता उपलब्ध नाही."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध नाही"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index c6b9210..3c0675b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Pembetulan warna"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mod sebelah tangan"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Amat malap"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Peranti pendengaran"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dihidupkan."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dimatikan."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tekan dan tahan kedua-dua kekunci kelantangan selama tiga saat untuk menggunakan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Hidupkan apl kerja?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Dapatkan akses kepada apl kerja dan pemberitahuan anda"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Hidupkan"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Apl tidak tersedia"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak tersedia sekarang."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> tidak tersedia"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 7e113a5..9c1f5ff 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"အရောင် အမှန်ပြင်ခြင်း"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"လက်တစ်ဖက်သုံးမုဒ်"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ပိုမှိန်ခြင်း"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"နားကြားကိရိယာ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်လိုက်သည်။"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ပိတ်လိုက်သည်။"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ကို သုံးရန် အသံအတိုးအလျှော့ ခလုတ်နှစ်ခုလုံးကို သုံးစက္ကန့်ကြာ ဖိထားပါ"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"အလုပ်သုံးအက်ပ်များ ဖွင့်မလား။"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"သင့်အလုပ်သုံးအက်ပ်နှင့် အကြောင်းကြားချက်များသုံးခွင့် ရယူပါ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ဖွင့်ရန်"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"အက်ပ်ကို မရနိုင်ပါ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို ယခု မရနိုင်ပါ။"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> မရနိုင်ပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 922f8f7..1d231fe 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Fargekorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndsmodus"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dimmet"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått på."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått av."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Trykk og hold inne begge volumtastene i tre sekunder for å bruke <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vil du slå på jobbapper?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Få tilgang til jobbapper og -varsler"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Slå på"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Appen er ikke tilgjengelig"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> er ikke tilgjengelig for øyeblikket."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> er utilgjengelig"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b8f8dd9..54c24b5 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"रङ सच्याउने सुविधा"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"हियरिङ डिभाइसहरू"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> प्रयोग गर्न दुवै भोल्युम कुञ्जीहरूलाई तीन सेकेन्डसम्म थिचिराख्नुहोस्"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"कामसम्बन्धी एपहरू अन गर्ने हो?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"कामसम्बन्धी एप चलाउने र सूचना प्राप्त गर्ने सुविधा अन गर्नुहोस्"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"अन गर्नुहोस्"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"एप उपलब्ध छैन"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले उपलब्ध छैन।"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> उपलब्ध छैन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index aa6d168..da34559 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Kleurcorrectie"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Bediening met 1 hand"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dimmen"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hoortoestellen"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat aan."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat uit."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Houd beide volumetoetsen drie seconden ingedrukt om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> te gebruiken"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Werk-apps aanzetten?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Krijg toegang tot je werk-apps en meldingen"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aanzetten"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"App is niet beschikbaar"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> is momenteel niet beschikbaar."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> niet beschikbaar"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b415908..5cb0b9d 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ରଙ୍ଗ ସଂଶୋଧନ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ଏକ-ହାତ ମୋଡ୍"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତ୍ୟଧିକ ଡିମ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ହିଅରିଂ ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବାକୁ ତିନି ସେକେଣ୍ଡ ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ ଦବାଇ ଧରି ରଖନ୍ତୁ"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ୱାର୍କ ଆପ୍ସ ଚାଲୁ କରିବେ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ଆପଣଙ୍କ ୱାର୍କ ଆପ୍ ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ ପାଆନ୍ତୁ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ଚାଲୁ କରନ୍ତୁ"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ଆପ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ନାହିଁ।"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ଉପଲବ୍ଧ ନାହିଁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 467a509..de05d46 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"ਰੰਗ ਸੁਧਾਈ"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ਇੱਕ ਹੱਥ ਮੋਡ"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਚਾਲੂ ਕਰਨੀਆਂ ਹਨ?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ਆਪਣੀਆਂ ਕੰਮ ਸੰਬੰਧੀ ਐਪਾਂ ਅਤੇ ਸੂਚਨਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ਚਾਲੂ ਕਰੋ"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਇਸ ਵੇਲੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f8b7753..9e0269b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korekcja kolorów"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tryb jednej ręki"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatkowe przyciemnienie"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Urządzenia słuchowe"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została włączona."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została wyłączona."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Naciśnij i przytrzymaj oba przyciski głośności przez trzy sekundy, by użyć usługi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Włączyć aplikacje służbowe?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Uzyskaj dostęp do służbowych aplikacji i powiadomień"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Włącz"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacja jest niedostępna"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest obecnie niedostępna."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – brak dostępu"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 9e182b4..ce1f686 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1531,7 +1531,7 @@
<string name="add_account_button_label" msgid="322390749416414097">"Adicionar conta"</string>
<string name="number_picker_increment_button" msgid="7621013714795186298">"Aumentar"</string>
<string name="number_picker_decrement_button" msgid="5116948444762708204">"Diminuir"</string>
- <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> toque e mantenha pressionado."</string>
+ <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> toque e pressione."</string>
<string name="number_picker_increment_scroll_action" msgid="8310191318914268271">"Deslize para cima para aumentar e para baixo para diminuir."</string>
<string name="time_picker_increment_minute_button" msgid="7195870222945784300">"Aumentar minuto"</string>
<string name="time_picker_decrement_minute_button" msgid="230925389943411490">"Diminuir minuto"</string>
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ativar apps de trabalho?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Acesse seus apps e notificações de trabalho"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string>
<string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ee48973..66bd560 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção da cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mais escuro"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"prima sem soltar as teclas de volume durante três segundos para usar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ativar as apps de trabalho?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Obtenha acesso às suas apps de trabalho e notificações"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"A app não está disponível"</string>
<string name="app_blocked_message" msgid="542972921087873023">"De momento, a app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9e182b4..ce1f686 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1531,7 +1531,7 @@
<string name="add_account_button_label" msgid="322390749416414097">"Adicionar conta"</string>
<string name="number_picker_increment_button" msgid="7621013714795186298">"Aumentar"</string>
<string name="number_picker_decrement_button" msgid="5116948444762708204">"Diminuir"</string>
- <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> toque e mantenha pressionado."</string>
+ <string name="number_picker_increment_scroll_mode" msgid="8403893549806805985">"<xliff:g id="VALUE">%s</xliff:g> toque e pressione."</string>
<string name="number_picker_increment_scroll_action" msgid="8310191318914268271">"Deslize para cima para aumentar e para baixo para diminuir."</string>
<string name="time_picker_increment_minute_button" msgid="7195870222945784300">"Aumentar minuto"</string>
<string name="time_picker_decrement_minute_button" msgid="230925389943411490">"Diminuir minuto"</string>
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Correção de cor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer a tela"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Toque nos dois botões de volume e os mantenha pressionados por três segundo para usar o <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ativar apps de trabalho?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Acesse seus apps e notificações de trabalho"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Ativar"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"O app não está disponível"</string>
<string name="app_blocked_message" msgid="542972921087873023">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não está disponível no momento."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> indisponível"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 18a8fcb..9663982 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Corecția culorilor"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modul cu o mână"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Luminozitate redusă suplimentar"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparate auditive"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Apasă ambele butoane de volum timp de trei secunde pentru a folosi <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Activezi aplicațiile pentru lucru?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Obține acces la aplicațiile și notificările pentru lucru"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Activează"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplicația nu este disponibilă"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu este disponibilă momentan."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nu este disponibilă"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 18c2150..ba548b3 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Коррекция цвета"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим управления одной рукой"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнительное уменьшение яркости"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слуховые аппараты"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Чтобы использовать сервис \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", нажмите и удерживайте обе клавиши громкости в течение трех секунд."</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Включить рабочие приложения?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Вы получите доступ к рабочим приложениям и уведомлениям"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Включить"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Приложение недоступно"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" сейчас недоступно."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 301e592..0363b0d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"වර්ණ නිවැරදි කිරීම"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"තනි අත් ප්රකාරය"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"තවත් අඳුරු"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ශ්රවණ උපාංග"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාත්මකයි."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාවිරහිතයි."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> භාවිත කිරීමට හඬ පරිමා යතුරු දෙකම තත්පර තුනකට ඔබාගෙන සිටින්න"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"කාර්යාල යෙදු. ක්රියා. කරන්නද?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"ඔබගේ කාර්යාල යෙදුම් සහ දැනුම්දීම් වෙත ප්රවේශය ලබා ගන්න"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ක්රියාත්මක කරන්න"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"යෙදුම ලබා ගත නොහැකිය"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> මේ දැන් ලබා ගත නොහැකිය."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> නොතිබේ"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index b4da379..e84bc83 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Úprava farieb"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednej ruky"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mimoriadne stmavenie"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Načúvacie zariadenia"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Ak chcete používať službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, pridržte tri sekundy oba klávesy hlasitosti"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Zapnúť pracovné aplikácie?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Získajte prístup k svojim pracovným aplikáciám a upozorneniam"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Zapnúť"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikácia nie je dostupná"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> nie je teraz dostupná."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nie je k dispozícii"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a076d40..52bef0b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Popravljanje barv"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enoročni način"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Zelo zatemnjen zaslon"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Za uporabo storitve <xliff:g id="SERVICE_NAME">%1$s</xliff:g> pritisnite obe tipki za glasnost in ju pridržite tri sekunde"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vklop delovnih aplikacij?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pridobite dostop do delovnih aplikacij in obvestil za delovni profil."</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Vklopi"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacija ni na voljo"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> trenutno ni na voljo."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"»<xliff:g id="ACTIVITY">%1$s</xliff:g>« ni na voljo"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 4b0fda9..d691fd0 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Korrigjimi i ngjyrës"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modaliteti i përdorimit me një dorë"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Shumë më i zbehtë"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Pajisjet e dëgjimit"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Shtyp dhe mbaj shtypur të dy butonat e volumit për tre sekonda për të përdorur <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Të aktivizohen aplikacionet e punës?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Merr qasje tek aplikacionet e punës dhe njoftimet e tua"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivizo"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Aplikacioni nuk ofrohet"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk ofrohet për momentin."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> nuk ofrohet"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7c5a570..aab16eb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1709,6 +1709,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекција боја"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим једном руком"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додатно затамњено"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни апарати"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је укључена."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је искључена."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Притисните и задржите оба тастера за јачину звука три секунде да бисте користили <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1943,6 +1944,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Укључујете пословне апликације?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Приступајте пословним апликацијама и обавештењима"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Укључи"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Апликација није доступна"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> тренутно није доступна."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> – није доступно"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 4a21b76..125999b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Färgkorrigering"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörapparater"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Tryck och håll båda volymknapparna i tre sekunder för att använda <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vill du aktivera jobbappar?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Få åtkomst till jobbappar och aviseringar"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aktivera"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Appen är inte tillgänglig"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> är inte tillgängligt just nu."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> är inte tillgänglig"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d72eb30..5cf2f77 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Usahihishaji wa rangi"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Hali ya kutumia kwa mkono mmoja"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Kipunguza mwangaza zaidi"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Vifaa vya kusaidia kusikia"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Bonyeza na ushikilie vitufe vyote viwili vya sauti kwa sekunde tatu ili utumie <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Iwashe programu za kazini?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Pata uwezo wa kufikia arifa na programu zako za kazini"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Washa"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Programu haipatikani"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> haipatikani hivi sasa."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> haipatikani"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 41279f6..8f576ab 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"கலர் கரெக்ஷன்"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ஒற்றைக் கைப் பயன்முறை"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"மிகக் குறைவான வெளிச்சம்"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"செவித்துணைக் கருவிகள்"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ஐப் பயன்படுத்த 3 விநாடிகளுக்கு இரண்டு ஒலியளவு பட்டன்களையும் அழுத்திப் பிடிக்கவும்"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"பணி ஆப்ஸை இயக்கவா?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"உங்கள் பணி ஆப்ஸுக்கும் அறிவிப்புகளுக்குமான அணுகலைப் பெறுங்கள்"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"இயக்கு"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"இந்த ஆப்ஸ் இப்போது கிடைப்பதில்லை"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் இப்போது கிடைப்பதில்லை."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> இல்லை"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b31f920..3cf745b 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"కలర్ కరెక్షన్"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"వన్-హ్యాండెడ్ మోడ్"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ఎక్స్ట్రా డిమ్"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"వినికిడి పరికరం"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>ని ఉపయోగించడానికి వాల్యూమ్ కీలు రెండింటినీ 3 సెకన్లు నొక్కి ఉంచండి"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"వర్క్ యాప్లను ఆన్ చేయాలా?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"మీ వర్క్ యాప్లు, నోటిఫికేషన్లకు యాక్సెస్ను పొందండి"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"ఆన్ చేయి"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"యాప్ అందుబాటులో లేదు"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రస్తుతం అందుబాటులో లేదు."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> అందుబాటులో లేదు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 843cd29..4afe454 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"การแก้สี"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"โหมดมือเดียว"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"หรี่แสงเพิ่มเติม"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"เครื่องช่วยฟัง"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้ 3 วินาทีเพื่อใช้ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"เปิดแอปงานใช่ไหม"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"รับสิทธิ์เข้าถึงแอปงานและการแจ้งเตือนต่างๆ"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"เปิด"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"แอปไม่พร้อมใช้งาน"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่พร้อมใช้งานในขณะนี้"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> ไม่พร้อมใช้งาน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f4e79d7..e808d56 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Pagtatama ng kulay"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Hand mode"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Mga hearing device"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Pindutin nang matagal ang parehong volume key sa loob ng tatlong segundo para magamit ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"I-on ang app para sa trabaho?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Makakuha ng access sa iyong mga app para sa trabaho at notification"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"I-on"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Hindi available ang app"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Hindi available sa ngayon ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Hindi available ang <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ae38880..5d471b3 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Renk düzeltme"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tek El modu"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra loş"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"İşitme cihazları"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini kullanmak için her iki ses tuşunu basılı tutun"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"İş uygulamaları açılsın mı?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"İş uygulamalarınıza ve bildirimlerinize erişin"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Aç"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Uygulama kullanılamıyor"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması şu anda kullanılamıyor."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kullanılamıyor"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 27cf840..1620c8f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1710,6 +1710,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Корекція кольору"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим керування однією рукою"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додаткове зменшення яскравості"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухові апарати"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Щоб скористатися службою <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, утримуйте обидві клавіші гучності впродовж трьох секунд"</string>
@@ -1944,6 +1945,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Увімкнути робочі додатки?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Отримайте доступ до своїх робочих додатків і сповіщень"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Увімкнути"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Додаток недоступний"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> зараз недоступний."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Недоступно: <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 0acea52..2b5b2f1 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"رنگ کی اصلاح"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ایک ہاتھ کی وضع"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"اضافی مدھم"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعتی آلات"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> کا استعمال کرنے کے لیے 3 سیکنڈ تک والیوم کی دونوں کلیدوں کو چھوئیں اور دبائے رکھیں"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"ورک ایپس آن کریں؟"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"اپنی ورک ایپس اور اطلاعات تک رسائی حاصل کریں"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"آن کریں"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"ایپ دستیاب نہیں ہے"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> ابھی دستیاب نہیں ہے۔"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> دستیاب نہیں ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index e30baba..6a88112 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ranglarni tuzatish"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ixcham rejim"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Juda xira"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eshitish qurilmalari"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> yoqildi."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> faolsizlantirildi."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatidan foydalanish uchun ikkala ovoz balandligi tugmalarini uzoq bosib turing"</string>
@@ -1942,6 +1943,8 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Ishga oid ilovalar yoqilsinmi?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Ishga oid ilovalaringiz va bildirishnomalarga ruxsat oling"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string>
+ <string name="work_mode_emergency_call_button" msgid="6818855962881612322">"Favqulodda holat"</string>
+ <string name="work_mode_dialer_off_message" msgid="2193299184850387465">"Ishga oid ilovalaringiz va chaqiruvlarga ruxsat oling"</string>
<string name="app_blocked_title" msgid="7353262160455028160">"Ilova ishlamayapti"</string>
<string name="app_blocked_message" msgid="542972921087873023">"Ayni vaqtda <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi ishlamayapti."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g> kanali ish faoliyatida emas"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b589b24..258d4ce 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -830,7 +830,7 @@
<string-array name="phoneTypes">
<item msgid="8996339953292723951">"Nhà riêng"</item>
<item msgid="7740243458912727194">"Di động"</item>
- <item msgid="8526146065496663766">"Cơ quan"</item>
+ <item msgid="8526146065496663766">"Nơi làm việc"</item>
<item msgid="8150904584178569699">"Số fax cơ quan"</item>
<item msgid="4537253139152229577">"Số fax nhà riêng"</item>
<item msgid="6751245029698664340">"Số máy nhắn tin"</item>
@@ -839,24 +839,24 @@
</string-array>
<string-array name="emailAddressTypes">
<item msgid="7786349763648997741">"Nhà riêng"</item>
- <item msgid="435564470865989199">"Cơ quan"</item>
+ <item msgid="435564470865989199">"Nơi làm việc"</item>
<item msgid="4199433197875490373">"Khác"</item>
<item msgid="3233938986670468328">"Tùy chỉnh"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="3861463339764243038">"Nhà riêng"</item>
- <item msgid="5472578890164979109">"Cơ quan"</item>
+ <item msgid="5472578890164979109">"Nơi làm việc"</item>
<item msgid="5718921296646594739">"Khác"</item>
<item msgid="5523122236731783179">"Tùy chỉnh"</item>
</string-array>
<string-array name="imAddressTypes">
<item msgid="588088543406993772">"Nhà riêng"</item>
- <item msgid="5503060422020476757">"Cơ quan"</item>
+ <item msgid="5503060422020476757">"Nơi làm việc"</item>
<item msgid="2530391194653760297">"Khác"</item>
<item msgid="7640927178025203330">"Tùy chỉnh"</item>
</string-array>
<string-array name="organizationTypes">
- <item msgid="6144047813304847762">"Cơ quan"</item>
+ <item msgid="6144047813304847762">"Nơi làm việc"</item>
<item msgid="7402720230065674193">"Khác"</item>
<item msgid="808230403067569648">"Tùy chỉnh"</item>
</string-array>
@@ -873,7 +873,7 @@
<string name="phoneTypeCustom" msgid="5120365721260686814">"Tùy chỉnh"</string>
<string name="phoneTypeHome" msgid="3880132427643623588">"Nhà riêng"</string>
<string name="phoneTypeMobile" msgid="1178852541462086735">"Di động"</string>
- <string name="phoneTypeWork" msgid="6604967163358864607">"Cơ quan"</string>
+ <string name="phoneTypeWork" msgid="6604967163358864607">"Nơi làm việc"</string>
<string name="phoneTypeFaxWork" msgid="6757519896109439123">"Số fax cơ quan"</string>
<string name="phoneTypeFaxHome" msgid="6678559953115904345">"Số fax nhà riêng"</string>
<string name="phoneTypePager" msgid="576402072263522767">"Số máy nhắn tin"</string>
@@ -897,16 +897,16 @@
<string name="eventTypeOther" msgid="530671238533887997">"Khác"</string>
<string name="emailTypeCustom" msgid="1809435350482181786">"Tùy chỉnh"</string>
<string name="emailTypeHome" msgid="1597116303154775999">"Nhà riêng"</string>
- <string name="emailTypeWork" msgid="2020095414401882111">"Cơ quan"</string>
+ <string name="emailTypeWork" msgid="2020095414401882111">"Nơi làm việc"</string>
<string name="emailTypeOther" msgid="5131130857030897465">"Khác"</string>
<string name="emailTypeMobile" msgid="787155077375364230">"Di Động"</string>
<string name="postalTypeCustom" msgid="5645590470242939129">"Tùy chỉnh"</string>
<string name="postalTypeHome" msgid="7562272480949727912">"Nhà riêng"</string>
- <string name="postalTypeWork" msgid="8553425424652012826">"Cơ quan"</string>
+ <string name="postalTypeWork" msgid="8553425424652012826">"Nơi làm việc"</string>
<string name="postalTypeOther" msgid="7094245413678857420">"Khác"</string>
<string name="imTypeCustom" msgid="5653384545085765570">"Tùy chỉnh"</string>
<string name="imTypeHome" msgid="6996507981044278216">"Nhà riêng"</string>
- <string name="imTypeWork" msgid="2099668940169903123">"Cơ quan"</string>
+ <string name="imTypeWork" msgid="2099668940169903123">"Nơi làm việc"</string>
<string name="imTypeOther" msgid="8068447383276219810">"Khác"</string>
<string name="imProtocolCustom" msgid="4437878287653764692">"Tùy chỉnh"</string>
<string name="imProtocolAim" msgid="4050198236506604378">"AIM"</string>
@@ -918,7 +918,7 @@
<string name="imProtocolIcq" msgid="2410325380427389521">"ICQ"</string>
<string name="imProtocolJabber" msgid="7919269388889582015">"Jabber"</string>
<string name="imProtocolNetMeeting" msgid="4985002408136148256">"NetMeeting"</string>
- <string name="orgTypeWork" msgid="8684458700669564172">"Cơ quan"</string>
+ <string name="orgTypeWork" msgid="8684458700669564172">"Nơi làm việc"</string>
<string name="orgTypeOther" msgid="5450675258408005553">"Khác"</string>
<string name="orgTypeCustom" msgid="1126322047677329218">"Tùy chỉnh"</string>
<string name="relationTypeCustom" msgid="282938315217441351">"Tùy chỉnh"</string>
@@ -938,7 +938,7 @@
<string name="relationTypeSpouse" msgid="6916682664436031703">"Vợ/chồng"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"Tùy chỉnh"</string>
<string name="sipAddressTypeHome" msgid="5918441930656878367">"Nhà riêng"</string>
- <string name="sipAddressTypeWork" msgid="7873967986701216770">"Cơ quan"</string>
+ <string name="sipAddressTypeWork" msgid="7873967986701216770">"Nơi làm việc"</string>
<string name="sipAddressTypeOther" msgid="6317012577345187275">"Khác"</string>
<string name="quick_contacts_not_available" msgid="1262709196045052223">"Không tìm thấy ứng dụng nào để xem liên hệ này."</string>
<string name="keyguard_password_enter_pin_code" msgid="6401406801060956153">"Nhập mã PIN"</string>
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Chỉnh màu"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Chế độ một tay"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Siêu tối"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Thiết bị trợ thính"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Nhấn và giữ đồng thời cả hai phím âm lượng trong 3 giây để sử dụng <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Bật các ứng dụng công việc?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Bạn sẽ có quyền truy cập vào các ứng dụng công việc và thông báo"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Bật"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Ứng dụng này không dùng được"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện không dùng được."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"Không hỗ trợ <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index a0ede11..9b998c1 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"单手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"极暗"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助听设备"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同时按住两个音量键 3 秒钟即可使用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"要开启工作应用访问权限吗?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"获取工作应用和通知的访问权限"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"开启"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"应用无法使用"</string>
<string name="app_blocked_message" msgid="542972921087873023">"<xliff:g id="APP_NAME">%1$s</xliff:g>目前无法使用。"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>不可用"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 3fcf138..065968c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已開啟。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已關閉。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"㩒住兩個音量鍵 3 秒就可以用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"要開啟工作應用程式存取權嗎?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"開啟工作應用程式和通知的存取權"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"無法使用應用程式"</string>
<string name="app_blocked_message" msgid="542972921087873023">"目前無法使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」。"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法使用「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 69e8c13..fd94101 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"色彩校正"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已開啟。"</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已關閉。"</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"同時按住調低及調高音量鍵三秒即可使用「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"要開啟工作應用程式存取權嗎?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"開啟工作應用程式和通知的存取權"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"開啟"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"應用程式無法使用"</string>
<string name="app_blocked_message" msgid="542972921087873023">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」目前無法使用。"</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"無法存取「<xliff:g id="ACTIVITY">%1$s</xliff:g>」"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 789f5c4..2d17ae2 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1708,6 +1708,7 @@
<string name="color_correction_feature_name" msgid="7975133554160979214">"Ukulungiswa kombala"</string>
<string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Imodi yesandla esisodwa"</string>
<string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ukufiphaza okwengeziwe"</string>
+ <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Amadivayizi okuzwa"</string>
<string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string>
<string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string>
<string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Cindezela uphinde ubambe bobabili okhiye bevolumu ngamasekhondi amathathu ukuze usebenzise i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
@@ -1942,6 +1943,10 @@
<string name="work_mode_off_title" msgid="961171256005852058">"Vula ama-app okusebenza womsebenzi?"</string>
<string name="work_mode_off_message" msgid="7319580997683623309">"Thola ukufinyelela kuma-app akho womsebenzi kanye nezaziso"</string>
<string name="work_mode_turn_on" msgid="3662561662475962285">"Vula"</string>
+ <!-- no translation found for work_mode_emergency_call_button (6818855962881612322) -->
+ <skip />
+ <!-- no translation found for work_mode_dialer_off_message (2193299184850387465) -->
+ <skip />
<string name="app_blocked_title" msgid="7353262160455028160">"Uhlelo lokusebenza alutholakali"</string>
<string name="app_blocked_message" msgid="542972921087873023">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayitholakali khona manje."</string>
<string name="app_streaming_blocked_title" msgid="6090945835898766139">"okungatholakali <xliff:g id="ACTIVITY">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1b6f88f..22d741c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3299,6 +3299,8 @@
<enum name="grab" value="1020" />
<!-- Pointer icon of a hand sign while grabbing something. -->
<enum name="grabbing" value="1021" />
+ <!-- Pointer icon indicating handwriting. -->
+ <enum name="handwriting" value="1022"/>
</attr>
<!-- Whether this view has elements that may overlap when drawn. See
@@ -9307,6 +9309,8 @@
<attr name="pointerIconGrab" format="reference"/>
<!-- Reference to a pointer drawable with STYLE_GRABBING. -->
<attr name="pointerIconGrabbing" format="reference"/>
+ <!-- Reference to a pointer drawable with HANDWRITING. -->
+ <attr name="pointerIconHandwriting" format="reference"/>
</declare-styleable>
<declare-styleable name="PointerIcon">
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index ef94484..11a4ed7 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1720,8 +1720,10 @@
<p>Requires the app to hold the permission
{@link android.Manifest.permission#FOREGROUND_SERVICE_FILE_MANAGEMENT} in order to use
this type.
+
+ TODO: b/258855262 mark this field as {@code hide} once this bug is fixed.
+ <flag name="fileManagement" value="0x1000" />
-->
- <flag name="fileManagement" value="0x1000" />
<!-- Use cases that can't be categorized into any other foreground service types, but also
can't use @link android.app.job.JobInfo.Builder} APIs.
See {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SPECIAL_USE} for the
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index ea6e1f1..a99ba15 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -72,8 +72,8 @@
<item name="secondary_content_alpha_material_dark" format="float" type="dimen">.7</item>
<item name="secondary_content_alpha_material_light" format="float" type="dimen">0.60</item>
- <item name="highlight_alpha_material_light" format="float" type="dimen">0.10</item>
- <item name="highlight_alpha_material_dark" format="float" type="dimen">0.10</item>
+ <item name="highlight_alpha_material_light" format="float" type="dimen">0.5</item>
+ <item name="highlight_alpha_material_dark" format="float" type="dimen">0.5</item>
<item name="highlight_alpha_material_colored" format="float" type="dimen">0.10</item>
<!-- Primary & accent colors -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c3ebef0..be22095 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2003,6 +2003,9 @@
STREAM_MUSIC as if it's on TV platform. -->
<bool name="config_single_volume">false</bool>
+ <!-- Volume policy -->
+ <bool name="config_volume_down_to_enter_silent">false</bool>
+
<!-- The number of volume steps for the notification stream -->
<integer name="config_audio_notif_vol_steps">7</integer>
@@ -4098,7 +4101,9 @@
exists on the device, the accessibility shortcut will be disabled by default. -->
<string name="config_defaultAccessibilityService" translatable="false"></string>
- <!-- Flag indicates that whether escrow token API is enabled for TrustAgent -->
+ <!-- URI for default Accessibility notification sound when to enable accessibility shortcut. -->
+ <string name="config_defaultAccessibilityNotificationSound" translatable="false"></string>
+
<!-- Warning: This API can be dangerous when not implemented properly. In particular,
escrow token must NOT be retrievable from device storage. In other words, either
escrow token is not stored on device or its ciphertext is stored on device while
@@ -5032,10 +5037,8 @@
<!-- If face auth sends the user directly to home/last open app, or stays on keyguard -->
<bool name="config_faceAuthDismissesKeyguard">true</bool>
- <!-- Default value for whether a SFPS device is required to be
- {@link KeyguardUpdateMonitor#isDeviceInteractive()} for fingerprint auth
- to unlock the device. -->
- <bool name="config_requireScreenOnToAuthEnabled">false</bool>
+ <!-- Default value for performant auth feature. -->
+ <bool name="config_performantAuthDefault">false</bool>
<!-- The component name for the default profile supervisor, which can be set as a profile owner
even after user setup is complete. The defined component should be used for supervision purposes
@@ -5414,6 +5417,9 @@
<!-- Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. -->
<bool name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled">false</bool>
+ <!-- Whether using display aspect ratio as a default aspect ratio for all letterboxed apps. -->
+ <bool name="config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled">false</bool>
+
<!-- Whether the specific behaviour for translucent activities letterboxing is enabled.
TODO(b/255532890) Enable when ignoreOrientationRequest is set -->
<bool name="config_letterboxIsEnabledForTranslucentActivities">false</bool>
@@ -5802,6 +5808,7 @@
- config_roundedCornerDrawableArray (config in SystemUI resource)
- config_roundedCornerTopDrawableArray (config in SystemUI resource)
- config_roundedCornerBottomDrawableArray (config in SystemUI resource)
+ - config_displayUsiVersionArray
Leave this array empty for single display device and the system will load the default main
built-in related configs.
@@ -5942,6 +5949,10 @@
When this resource is empty, that button will not be shown. -->
<string name="config_supervisedUserCreationPackage" translatable="false"></string>
+ <!-- Flag indicating whether the show Stylus pointer icon.
+ If set, a pointer icon will be shown over the location of a stylus pointer.-->
+ <bool name="config_enableStylusPointerIcon">false</bool>
+
<!-- Determines whether SafetyCenter feature is enabled. -->
<bool name="config_enableSafetyCenter">true</bool>
@@ -6160,4 +6171,21 @@
trusted certificate using the SHA-256 digest algorithm. -->
<string-array name="config_healthConnectMigrationKnownSigners">
</string-array>
+
+ <!-- The Universal Stylus Initiative (USI) protocol version supported by each display.
+ (@see https://universalstylus.org/).
+
+ The i-th value in this array corresponds to the supported USI version of the i-th display
+ listed in config_displayUniqueIdArray. On a single-display device, the
+ config_displayUniqueIdArray may be empty, in which case the only value in this array should
+ be the USI version for the main built-in display.
+
+ If the display does not support USI, the version value should be an empty string. If the
+ display supports USI, the version must be in the following format:
+ "<major-version>.<minor-version>"
+
+ For example, "", "1.0", and "2.0" are valid values. -->
+ <string-array name="config_displayUsiVersionArray" translatable="false">
+ <item>""</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 0a7ffca..79964b3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1419,6 +1419,7 @@
<item name="pointerIconZoomOut">@drawable/pointer_zoom_out_icon</item>
<item name="pointerIconGrab">@drawable/pointer_grab_icon</item>
<item name="pointerIconGrabbing">@drawable/pointer_grabbing_icon</item>
+ <item name="pointerIconHandwriting">@drawable/pointer_handwriting_icon</item>
</style>
<style name="LargePointer">
@@ -1455,6 +1456,7 @@
<item name="pointerIconZoomOut">@drawable/pointer_zoom_out_large_icon</item>
<item name="pointerIconGrab">@drawable/pointer_grab_large_icon</item>
<item name="pointerIconGrabbing">@drawable/pointer_grabbing_large_icon</item>
+ <item name="pointerIconHandwriting">@drawable/pointer_handwriting_icon</item>
</style>
<!-- @hide -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 89a28d5..2715c94 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -328,6 +328,7 @@
<java-symbol type="bool" name="config_use_strict_phone_number_comparation_for_kazakhstan" />
<java-symbol type="integer" name="config_phonenumber_compare_min_match" />
<java-symbol type="bool" name="config_single_volume" />
+ <java-symbol type="bool" name="config_volume_down_to_enter_silent" />
<java-symbol type="bool" name="config_voice_capable" />
<java-symbol type="bool" name="config_requireCallCapableAccountForHandle" />
<java-symbol type="bool" name="config_user_notification_of_restrictied_mobile_access" />
@@ -2656,7 +2657,7 @@
<java-symbol type="array" name="config_face_acquire_vendor_biometricprompt_ignorelist" />
<java-symbol type="bool" name="config_faceAuthSupportsSelfIllumination" />
<java-symbol type="bool" name="config_faceAuthDismissesKeyguard" />
- <java-symbol type="bool" name="config_requireScreenOnToAuthEnabled" />
+ <java-symbol type="bool" name="config_performantAuthDefault" />
<!-- Face config -->
<java-symbol type="integer" name="config_faceMaxTemplatesPerUser" />
@@ -3480,6 +3481,7 @@
<java-symbol type="string" name="color_correction_feature_name" />
<java-symbol type="string" name="reduce_bright_colors_feature_name" />
<java-symbol type="string" name="config_defaultAccessibilityService" />
+ <java-symbol type="string" name="config_defaultAccessibilityNotificationSound" />
<java-symbol type="string" name="accessibility_shortcut_spoken_feedback" />
<java-symbol type="string" name="accessibility_select_shortcut_menu_title" />
@@ -4441,6 +4443,7 @@
<java-symbol type="bool" name="config_letterboxIsEducationEnabled" />
<java-symbol type="dimen" name="config_letterboxDefaultMinAspectRatioForUnresizableApps" />
<java-symbol type="bool" name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled" />
+ <java-symbol type="bool" name="config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled" />
<java-symbol type="bool" name="config_isCompatFakeFocusEnabled" />
<java-symbol type="bool" name="config_isWindowManagerCameraCompatTreatmentEnabled" />
<java-symbol type="bool" name="config_isCameraCompatControlForStretchedIssuesEnabled" />
@@ -4778,6 +4781,7 @@
<java-symbol type="array" name="config_mainBuiltInDisplayWaterfallCutout" />
<java-symbol type="array" name="config_secondaryBuiltInDisplayWaterfallCutout" />
<java-symbol type="array" name="config_waterfallCutoutArray" />
+ <java-symbol type="array" name="config_displayUsiVersionArray" />
<java-symbol type="fraction" name="global_actions_vertical_padding_percentage" />
<java-symbol type="fraction" name="global_actions_horizontal_padding_percentage" />
@@ -4809,6 +4813,8 @@
<java-symbol type="string" name="config_supervisedUserCreationPackage"/>
+ <java-symbol type="bool" name="config_enableStylusPointerIcon" />
+
<java-symbol type="bool" name="config_enableSafetyCenter" />
<java-symbol type="bool" name="config_safetyProtectionEnabled" />
diff --git a/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt b/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
index 966d362..9acb99a 100644
--- a/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
+++ b/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
@@ -92,9 +92,9 @@
}
fun makeIntentSender(sessionId: Int) = PendingIntent.getBroadcast(context, sessionId,
- Intent(INTENT_ACTION),
+ Intent(INTENT_ACTION).setPackage(context.packageName),
PendingIntent.FLAG_UPDATE_CURRENT
- or PendingIntent.FLAG_MUTABLE_UNAUDITED).intentSender
+ or PendingIntent.FLAG_MUTABLE).intentSender
fun getResult(unit: TimeUnit, timeout: Long) = results.poll(timeout, unit)
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index bcb13d2..4548730 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -248,7 +248,9 @@
@Test
public void allPendingIntents_containsCustomRemoteViews() {
- PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent("test"), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent intent = PendingIntent.getActivity(mContext, 0,
+ new Intent("test").setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_MUTABLE);
RemoteViews contentView = new RemoteViews(mContext.getPackageName(), 0 /* layoutId */);
contentView.setOnClickPendingIntent(1 /* id */, intent);
@@ -1578,7 +1580,8 @@
* Creates a PendingIntent with the given action.
*/
private PendingIntent createPendingIntent(String action) {
- return PendingIntent.getActivity(mContext, 0, new Intent(action),
+ return PendingIntent.getActivity(mContext, 0,
+ new Intent(action).setPackage(mContext.getPackageName()),
PendingIntent.FLAG_MUTABLE);
}
}
diff --git a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
index 05775bc..1b52f80 100644
--- a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
+++ b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
@@ -32,14 +32,16 @@
registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED);
addIntermediate("after-register");
PendingIntent is = PendingIntent.getBroadcast(getContext(), 0,
- makeBroadcastIntent(BROADCAST_REGISTERED), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ makeBroadcastIntent(BROADCAST_REGISTERED).setPackage(getContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE);
is.send();
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
}
public void testRegisteredReceivePermissionDenied() throws Exception {
- final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED);
+ final Intent intent = makeBroadcastIntent(BROADCAST_REGISTERED)
+ .setPackage(getContext().getPackageName());
setExpectedReceivers(new String[]{RECEIVER_RESULTS});
registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_DENIED);
@@ -52,7 +54,8 @@
}
};
- PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent,
+ PendingIntent.FLAG_MUTABLE);
is.send(Activity.RESULT_CANCELED, finish, null);
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
@@ -61,14 +64,16 @@
public void testLocalReceivePermissionGranted() throws Exception {
setExpectedReceivers(new String[]{RECEIVER_LOCAL});
PendingIntent is = PendingIntent.getBroadcast(getContext(), 0,
- makeBroadcastIntent(BROADCAST_LOCAL_GRANTED), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ makeBroadcastIntent(BROADCAST_LOCAL_GRANTED)
+ .setPackage(getContext().getPackageName()), PendingIntent.FLAG_MUTABLE);
is.send();
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
}
public void testLocalReceivePermissionDenied() throws Exception {
- final Intent intent = makeBroadcastIntent(BROADCAST_LOCAL_DENIED);
+ final Intent intent = makeBroadcastIntent(BROADCAST_LOCAL_DENIED)
+ .setPackage(getContext().getPackageName());
setExpectedReceivers(new String[]{RECEIVER_RESULTS});
@@ -79,7 +84,8 @@
}
};
- PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent,
+ PendingIntent.FLAG_MUTABLE);
is.send(Activity.RESULT_CANCELED, finish, null);
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 0c7ff4a..627feab 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -35,13 +35,19 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
+import android.hardware.vibrator.IVibrator;
import android.net.Uri;
+import android.os.SystemVibrator;
import android.os.VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException;
+import android.os.Vibrator;
+import android.os.VibratorInfo;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.StepSegment;
import android.platform.test.annotations.Presubmit;
+import androidx.test.InstrumentationRegistry;
+
import com.android.internal.R;
import org.junit.Test;
@@ -770,6 +776,45 @@
}
@Test
+ public void testAreVibrationFeaturesSupported_allSegmentsSupported() {
+ Vibrator vibrator =
+ createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
+ .build());
+
+ assertTrue(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3}, /* repeatIndex= */ -1)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 40},
+ /* repeatIndex= */ 2)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(
+ VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+ .repeatEffectIndefinitely(TEST_ONE_SHOT)
+ .compose()
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testAreVibrationFeaturesSupported_withUnsupportedSegments() {
+ Vibrator vibrator =
+ createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1).build());
+
+ assertFalse(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addEffect(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 40},
+ /* repeatIndex= */ -1))
+ .compose()
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
public void testIsHapticFeedbackCandidate_repeatingEffects_notCandidates() {
assertFalse(VibrationEffect.createWaveform(
new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0).isHapticFeedbackCandidate());
@@ -890,4 +935,13 @@
return context;
}
+
+ private Vibrator createVibratorWithCustomInfo(VibratorInfo info) {
+ return new SystemVibrator(InstrumentationRegistry.getContext()) {
+ @Override
+ public VibratorInfo getInfo() {
+ return info;
+ }
+ };
+ }
}
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index c59a3f5..375fdac 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -586,6 +586,189 @@
assertEquals(new VibrationAttributes.Builder().build(), vibrationAttributes);
}
+ @Test
+ public void areVibrationFeaturesSupported_noAmplitudeControl_fractionalAmplitudes() {
+ Vibrator vibrator =
+ createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedEffects(VibrationEffect.EFFECT_THUD)
+ .build());
+
+ // Have at least one fractional amplitude (amplitude not min (0) or max (255) or DEFAULT).
+ assertFalse(vibrator.areVibrationFeaturesSupported(waveformWithAmplitudes(10, 30)));
+ assertFalse(vibrator.areVibrationFeaturesSupported(waveformWithAmplitudes(10, 255)));
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, /* amplitude= */ 40)));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_noAmplitudeControl_nonFractionalAmplitudes() {
+ Vibrator vibrator =
+ createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedEffects(VibrationEffect.EFFECT_THUD)
+ .build());
+
+ // All amplitudes are min, max, or default. Requires no amplitude control.
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ waveformWithAmplitudes(255, 0, VibrationEffect.DEFAULT_AMPLITUDE, 255)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3}, /* repeatIndex= */ -1)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, VibrationEffect.DEFAULT_AMPLITUDE)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, /* amplitude= */ 255)));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_withAmplitudeControl() {
+ Vibrator vibrator =
+ createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
+ .build());
+
+ // All forms of amplitudes are valid when amplitude control is available.
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ waveformWithAmplitudes(255, 0, VibrationEffect.DEFAULT_AMPLITUDE, 255)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3}, /* repeatIndex= */ -1)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(waveformWithAmplitudes(10, 30, 50)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ waveformWithAmplitudes(7, 255, 0, 0, 60)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, VibrationEffect.DEFAULT_AMPLITUDE)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, /* amplitude= */ 255)));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.createOneShot(20, /* amplitude= */ 40)));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_primitiveCompositionsWithSupportedPrimitives() {
+ Vibrator vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
+ .build());
+
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose()));
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_CLICK,
+ /* scale= */ 0.2f,
+ /* delay= */ 200)
+ .compose()));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_primitiveCompositionsWithUnupportedPrimitives() {
+ Vibrator vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
+ .build());
+
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .compose()));
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK)
+ .compose()));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_composedEffects_allComponentsSupported() {
+ Vibrator vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
+ .setSupportedEffects(VibrationEffect.EFFECT_TICK, VibrationEffect.EFFECT_POP)
+ .build());
+
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addEffect(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 255},
+ /* repeatIndex= */ -1))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_POP))
+ .compose()));
+
+ vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD, 10)
+ .setSupportedEffects(VibrationEffect.EFFECT_POP, VibrationEffect.EFFECT_CLICK)
+ .build());
+
+ assertTrue(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .addEffect(VibrationEffect.createWaveform(
+ // These timings are given either 0 or default amplitudes, which
+ // do not require vibrator's amplitude control.
+ /* timings= */ new long[] {1, 2, 3},
+ /* repeatIndex= */ -1))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_POP))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
+ .compose()));
+ }
+
+ @Test
+ public void areVibrationFeaturesSupported_composedEffects_someComponentsUnupported() {
+ Vibrator vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 10)
+ .setSupportedEffects(VibrationEffect.EFFECT_TICK, VibrationEffect.EFFECT_POP)
+ .build());
+
+ // Not supported due to the TICK primitive, which the vibrator has no support for.
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .addEffect(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 255},
+ /* repeatIndex= */ -1))
+ .compose()));
+ // Not supported due to the THUD effect, which the vibrator has no support for.
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addEffect(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 255},
+ /* repeatIndex= */ -1))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_THUD))
+ .compose()));
+
+ vibrator = createVibratorWithCustomInfo(new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD, 10)
+ .setSupportedEffects(VibrationEffect.EFFECT_POP)
+ .build());
+
+ // Not supported due to fractional amplitudes (amplitudes not min (0) or max (255) or
+ // DEFAULT), because the vibrator has no amplitude control.
+ assertFalse(vibrator.areVibrationFeaturesSupported(
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .addEffect(VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {10, 20, 255},
+ /* repeatIndex= */ -1))
+ .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_POP))
+ .compose()));
+ }
+
/**
* Asserts that the frequency profile is empty, and therefore frequency control isn't supported.
*/
@@ -593,4 +776,21 @@
assertTrue(info.getFrequencyProfile().isEmpty());
assertEquals(false, info.hasCapability(IVibrator.CAP_FREQUENCY_CONTROL));
}
+
+ private Vibrator createVibratorWithCustomInfo(VibratorInfo info) {
+ return new SystemVibrator(mContextSpy) {
+ @Override
+ public VibratorInfo getInfo() {
+ return info;
+ }
+ };
+ }
+
+ private static VibrationEffect waveformWithAmplitudes(int...amplitudes) {
+ long[] timings = new long[amplitudes.length];
+ for (int i = 0; i < timings.length; i++) {
+ timings[i] = i * 2; // Arbitrary timings.
+ }
+ return VibrationEffect.createWaveform(timings, amplitudes, /* repeatIndex= */ -1);
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
index a0e1f43..9099274 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
@@ -25,9 +25,14 @@
import static org.testng.Assert.assertThrows;
import android.os.Parcel;
+import android.os.SystemVibrator;
import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.os.VibratorInfo;
import android.platform.test.annotations.Presubmit;
+import androidx.test.InstrumentationRegistry;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@@ -146,9 +151,149 @@
}
@Test
+ public void testVibrationFeaturesSupport_idsWithFallback_fallbackEnabled_vibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(
+ VibrationEffect.EFFECT_TICK,
+ VibrationEffect.EFFECT_CLICK,
+ VibrationEffect.EFFECT_DOUBLE_CLICK,
+ VibrationEffect.EFFECT_HEAVY_CLICK);
+
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_HEAVY_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithFallback_fallbackEnabled_noVibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(new int[0]);
+
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_HEAVY_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithFallback_fallbackDisabled_vibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(
+ VibrationEffect.EFFECT_TICK,
+ VibrationEffect.EFFECT_CLICK,
+ VibrationEffect.EFFECT_DOUBLE_CLICK,
+ VibrationEffect.EFFECT_HEAVY_CLICK);
+
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_HEAVY_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithFallback_fallbackDisabled_noVibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(new int[0]);
+
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_DOUBLE_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_HEAVY_CLICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithNoFallback_fallbackEnabled_vibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(
+ VibrationEffect.EFFECT_THUD,
+ VibrationEffect.EFFECT_POP,
+ VibrationEffect.EFFECT_TEXTURE_TICK);
+
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_THUD)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_POP)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithFallback(VibrationEffect.EFFECT_TEXTURE_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithNoFallback_fallbackEnabled_noVibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(new int[0]);
+
+ assertFalse(createSegmentWithFallback(VibrationEffect.EFFECT_THUD)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithFallback(VibrationEffect.EFFECT_POP)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithFallback(VibrationEffect.EFFECT_TEXTURE_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithNoFallback_fallbackDisabled_vibratorSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(
+ VibrationEffect.EFFECT_THUD,
+ VibrationEffect.EFFECT_POP,
+ VibrationEffect.EFFECT_TEXTURE_TICK);
+
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_THUD)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_POP)
+ .areVibrationFeaturesSupported(vibrator));
+ assertTrue(createSegmentWithoutFallback(VibrationEffect.EFFECT_TEXTURE_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_idsWithNoFallback_fallbackDisabled_noVibSupport() {
+ Vibrator vibrator = createVibratorWithSupportedEffects(new int[0]);
+
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_THUD)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_POP)
+ .areVibrationFeaturesSupported(vibrator));
+ assertFalse(createSegmentWithoutFallback(VibrationEffect.EFFECT_TEXTURE_TICK)
+ .areVibrationFeaturesSupported(vibrator));
+ }
+
+ @Test
public void testIsHapticFeedbackCandidate_prebakedRingtones_notCandidates() {
assertFalse(new PrebakedSegment(
VibrationEffect.RINGTONES[1], true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
.isHapticFeedbackCandidate());
}
+
+ private static PrebakedSegment createSegmentWithFallback(int effectId) {
+ // note: arbitrary effect strength being used.
+ return new PrebakedSegment(effectId, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
+ }
+
+ private static PrebakedSegment createSegmentWithoutFallback(int effectId) {
+ // note: arbitrary effect strength being used.
+ return new PrebakedSegment(effectId, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
+ }
+
+ private static Vibrator createVibratorWithSupportedEffects(int... supportedEffects) {
+ return new SystemVibrator(InstrumentationRegistry.getContext()) {
+ @Override
+ public VibratorInfo getInfo() {
+ return new VibratorInfo.Builder(/* id= */ 1)
+ .setSupportedEffects(supportedEffects)
+ .build();
+ }
+ };
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
index a690553..298438f 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
@@ -17,15 +17,22 @@
package android.os.vibrator;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
import static org.testng.Assert.assertThrows;
+import android.hardware.vibrator.IVibrator;
import android.os.Parcel;
+import android.os.SystemVibrator;
import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.os.VibratorInfo;
import android.platform.test.annotations.Presubmit;
+import androidx.test.InstrumentationRegistry;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@@ -139,6 +146,38 @@
}
@Test
+ public void testVibrationFeaturesSupport_primitiveSupportedByVibrator() {
+ assertTrue(createSegment(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_CLICK)));
+ assertTrue(createSegment(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_THUD)));
+ assertTrue(createSegment(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_primitiveNotSupportedByVibrator() {
+ assertFalse(createSegment(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_THUD)));
+ assertFalse(createSegment(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_CLICK)));
+ assertFalse(createSegment(VibrationEffect.Composition.PRIMITIVE_THUD)
+ .areVibrationFeaturesSupported(
+ createVibratorWithSupportedPrimitive(
+ VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)));
+ }
+
+ @Test
public void testIsHapticFeedbackCandidate_returnsTrue() {
assertTrue(new PrimitiveSegment(
VibrationEffect.Composition.PRIMITIVE_NOOP, 1, 10).isHapticFeedbackCandidate());
@@ -151,4 +190,21 @@
assertTrue(new PrimitiveSegment(
VibrationEffect.Composition.PRIMITIVE_SPIN, 1, 10).isHapticFeedbackCandidate());
}
+
+ private static PrimitiveSegment createSegment(int primitiveId) {
+ // note: arbitrary scale and delay values being used.
+ return new PrimitiveSegment(primitiveId, 0.2f, 10);
+ }
+
+ private static Vibrator createVibratorWithSupportedPrimitive(int primitiveId) {
+ return new SystemVibrator(InstrumentationRegistry.getContext()) {
+ @Override
+ public VibratorInfo getInfo() {
+ return new VibratorInfo.Builder(/* id= */ 1)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS)
+ .setSupportedPrimitive(primitiveId, 10)
+ .build();
+ }
+ };
+ }
}
diff --git a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
index 3291b2d..6f8c205 100644
--- a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
@@ -16,26 +16,40 @@
package android.os.vibrator;
+import static android.os.VibrationEffect.DEFAULT_AMPLITUDE;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.os.Parcel;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.platform.test.annotations.Presubmit;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
@Presubmit
@RunWith(MockitoJUnitRunner.class)
public class RampSegmentTest {
private static final float TOLERANCE = 1e-2f;
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Mock
+ private Vibrator mVibrator;
+
@Test
public void testCreation() {
RampSegment ramp = new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
@@ -66,7 +80,7 @@
new RampSegment(0, 0, 0, 0, 0).validate();
assertThrows(IllegalArgumentException.class,
- () -> new RampSegment(VibrationEffect.DEFAULT_AMPLITUDE, 0, 0, 0, 0).validate());
+ () -> new RampSegment(DEFAULT_AMPLITUDE, 0, 0, 0, 0).validate());
assertThrows(IllegalArgumentException.class,
() -> new RampSegment(/* startAmplitude= */ -2, 0, 0, 0, 0).validate());
assertThrows(IllegalArgumentException.class,
@@ -142,6 +156,129 @@
}
@Test
+ public void testVibrationFeaturesSupport_amplitudeAndFrequencyControls_supported() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ // Increasing amplitude
+ assertTrue(new RampSegment(0.5f, 1, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ // Increasing frequency
+ assertTrue(new RampSegment(0.5f, 0.5f, 0, 1, 10).areVibrationFeaturesSupported(mVibrator));
+ // Decreasing amplitude
+ assertTrue(new RampSegment(1, 0.5f, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ // Decreasing frequency
+ assertTrue(new RampSegment(0.5f, 0.5f, 1, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ // Zero duration
+ assertTrue(new RampSegment(0.5f, 0.5f, 1, 0, 0).areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_noAmplitudeControl_unsupportedForChangingAmplitude() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ // Test with increasing/decreasing amplitudes.
+ assertFalse(new RampSegment(0.5f, 1, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(1, 0.5f, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_noAmplitudeControl_fractionalAmplitudeUnsupported() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ assertFalse(new RampSegment(0.2f, 0.2f, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(0, 0.2f, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(0.2f, 0, 0, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_unchangingZeroAmplitude_supported() {
+ RampSegment amplitudeZeroWithIncreasingFrequency = new RampSegment(1, 1, 0.5f, 0.8f, 10);
+ RampSegment amplitudeZeroWithDecreasingFrequency = new RampSegment(1, 1, 0.8f, 0.5f, 10);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(amplitudeZeroWithIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(amplitudeZeroWithDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(amplitudeZeroWithIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(amplitudeZeroWithDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_unchangingOneAmplitude_supported() {
+ RampSegment amplitudeOneWithIncreasingFrequency = new RampSegment(1, 1, 0.5f, 0.8f, 10);
+ RampSegment amplitudeOneWithDecreasingFrequency = new RampSegment(1, 1, 0.8f, 0.5f, 10);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(amplitudeOneWithIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(amplitudeOneWithDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(amplitudeOneWithIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(amplitudeOneWithDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_unchangingDefaultAmplitude_supported() {
+ RampSegment defaultAmplitudeIncreasingFrequency =
+ new RampSegment(DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE, 0.5f, 0.8f, 10);
+ RampSegment defaultAmplitudeDecreasingFrequency =
+ new RampSegment(DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE, 0.8f, 0.5f, 10);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(defaultAmplitudeIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(defaultAmplitudeDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(defaultAmplitudeIncreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(defaultAmplitudeDecreasingFrequency.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_noFrequencyControl_unsupportedForChangingFrequency() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+ when(mVibrator.hasFrequencyControl()).thenReturn(false);
+
+ // Test with increasing/decreasing frequencies.
+ assertFalse(new RampSegment(0, 0, 0.2f, 0.4f, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(0, 0, 0.4f, 0.2f, 10).areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_noFrequencyControl_fractionalFrequencyUnsupported() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+ when(mVibrator.hasFrequencyControl()).thenReturn(false);
+
+ assertFalse(new RampSegment(0, 0, 0.2f, 0.2f, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(0, 0, 0.2f, 0, 10).areVibrationFeaturesSupported(mVibrator));
+ assertFalse(new RampSegment(0, 0, 0, 0.2f, 10).areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_unchangingZeroFrequency_supported() {
+ RampSegment frequencyZeroWithIncreasingAmplitude = new RampSegment(0.1f, 1, 0, 0, 10);
+ RampSegment frequencyZeroWithDecreasingAmplitude = new RampSegment(1, 0.1f, 0, 0, 10);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+ when(mVibrator.hasFrequencyControl()).thenReturn(false);
+
+ assertTrue(frequencyZeroWithIncreasingAmplitude.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(frequencyZeroWithDecreasingAmplitude.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ assertTrue(frequencyZeroWithIncreasingAmplitude.areVibrationFeaturesSupported(mVibrator));
+ assertTrue(frequencyZeroWithDecreasingAmplitude.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
public void testIsHapticFeedbackCandidate_returnsTrue() {
// A single ramp segment duration is not checked here, but contributes to the effect known
// duration checked in VibrationEffect implementations.
diff --git a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
index 4424127..ade2161 100644
--- a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
@@ -21,21 +21,33 @@
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
import android.os.Parcel;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.platform.test.annotations.Presubmit;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
@Presubmit
@RunWith(MockitoJUnitRunner.class)
public class StepSegmentTest {
private static final float TOLERANCE = 1e-2f;
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Mock
+ private Vibrator mVibrator;
+
@Test
public void testCreation() {
StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequencyHz= */ 1f,
@@ -156,6 +168,95 @@
}
@Test
+ public void testVibrationFeaturesSupport_zeroAmplitude_supported() {
+ StepSegment segment =
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 0);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_maxAmplitude_supported() {
+ StepSegment segment =
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 0);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_defaultAmplitude_supported() {
+ StepSegment segment =
+ new StepSegment(
+ /* amplitude= */ VibrationEffect.DEFAULT_AMPLITUDE,
+ /* frequencyHz= */ 0,
+ /* duration= */ 0);
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_fractionalAmplitude_hasAmplitudeCtrl_supported() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(true);
+
+ assertTrue(new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 0, /* duration= */ 0)
+ .areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_fractionalAmplitude_hasNoAmplitudeCtrl_notSupported() {
+ when(mVibrator.hasAmplitudeControl()).thenReturn(false);
+
+ assertFalse(new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 0, /* duration= */ 0)
+ .areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_zeroFrequency_supported() {
+ StepSegment segment =
+ new StepSegment(/* amplitude= */ 0f, /* frequencyHz= */ 0, /* duration= */ 0);
+ when(mVibrator.hasFrequencyControl()).thenReturn(false);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_nonZeroFrequency_hasFrequencyCtrl_supported() {
+ StepSegment segment =
+ new StepSegment(/* amplitude= */ 0f, /* frequencyHz= */ 0.2f, /* duration= */ 0);
+ when(mVibrator.hasFrequencyControl()).thenReturn(true);
+
+ assertTrue(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
+ public void testVibrationFeaturesSupport_nonZeroFrequency_hasNoFrequencyCtrl_notSupported() {
+ StepSegment segment =
+ new StepSegment(/* amplitude= */ 0f, /* frequencyHz= */ 0.2f, /* duration= */ 0);
+ when(mVibrator.hasFrequencyControl()).thenReturn(false);
+
+ assertFalse(segment.areVibrationFeaturesSupported(mVibrator));
+ }
+
+ @Test
public void testIsHapticFeedbackCandidate_returnsTrue() {
// A single step segment duration is not checked here, but contributes to the effect known
// duration checked in VibrationEffect implementations.
diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
index 6186192..e0eb197 100644
--- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
+++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
@@ -48,7 +48,8 @@
public void setUp() {
final Context context = InstrumentationRegistry.getContext();
mTestIntent = PendingIntent.getActivity(context, 0 /* requestCode */,
- new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
+ new Intent().setPackage(context.getPackageName()),
+ PendingIntent.FLAG_MUTABLE /* flags */);
mIcon = Icon.createWithBitmap(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888));
}
diff --git a/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
new file mode 100644
index 0000000..7706d9a
--- /dev/null
+++ b/core/tests/coretests/src/android/text/method/InsertModeTransformationMethodTest.java
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.ReplacementSpan;
+import android.view.View;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InsertModeTransformationMethodTest {
+ private static View sView;
+ private static final String TEXT = "abc def";
+
+ @BeforeClass
+ public static void setupClass() {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ sView = new View(context);
+ }
+
+ @Test
+ public void transformedText_charAt() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, false, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final CharSequence expected =
+ TEXT.substring(0, offset) + "\n\n" + TEXT.substring(offset);
+
+ assertCharSequence(transformedText, expected);
+ }
+ }
+
+ @Test
+ public void transformedText_charAt_singleLine() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, true, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final CharSequence expected =
+ TEXT.substring(0, offset) + "\uFFFD" + TEXT.substring(offset);
+
+ assertCharSequence(transformedText, expected);
+ }
+ }
+
+ @Test
+ public void transformedText_charAt_editing() {
+ transformedText_charAt_editing(false, "\n\n");
+ }
+
+ @Test
+ public void transformedText_charAt_singleLine_editing() {
+ transformedText_charAt_editing(true, "\uFFFD");
+ }
+
+ public void transformedText_charAt_editing(boolean singleLine, String placeholder) {
+ final SpannableStringBuilder text = new SpannableStringBuilder(TEXT);
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, singleLine, null);
+ final CharSequence transformedText = transformationMethod.getTransformation(text, sView);
+ // TransformationMethod is set on the original text as a TextWatcher in the TextView.
+ text.setSpan(transformationMethod, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ assertCharSequence(transformedText, "abc" + placeholder + " def");
+
+ // original text is "abcxx def" after insertion.
+ text.insert(3, "xx");
+ assertCharSequence(transformedText, "abcxx" + placeholder + " def");
+
+ // original text is "abcxx vvdef" after insertion.
+ text.insert(6, "vv");
+ assertCharSequence(transformedText, "abcxx" + placeholder + " vvdef");
+
+ // original text is "abc vvdef" after deletion.
+ text.delete(3, 5);
+ assertCharSequence(transformedText, "abc" + placeholder + " vvdef");
+
+ // original text is "abc def" after deletion.
+ text.delete(4, 6);
+ assertCharSequence(transformedText, "abc" + placeholder + " def");
+
+ // original text is "abdef" after deletion.
+ // the placeholder is now inserted at index 2, since the deletion covers the index 3.
+ text.delete(2, 4);
+ assertCharSequence(transformedText, "ab" + placeholder + "def");
+
+ // original text is "axxdef" after replace.
+ text.replace(1, 2, "xx");
+ assertCharSequence(transformedText, "axx" + placeholder + "def");
+
+ // original text is "axxvvf" after replace.
+ text.replace(3, 5, "vv");
+ assertCharSequence(transformedText, "axx" + placeholder + "vvf");
+
+ // original text is "abc def" after replace.
+ // the placeholder is inserted at index 6 after the insertion, since the replacement covers
+ // the index 3.
+ text.replace(1, 5, "bc de");
+ assertCharSequence(transformedText, "abc de" + placeholder + "f");
+ }
+
+ @Test
+ public void transformedText_subSequence() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, false, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final CharSequence expected =
+ TEXT.substring(0, offset) + "\n\n" + TEXT.substring(offset);
+
+ for (int start = 0; start < transformedText.length(); ++start) {
+ for (int end = start; end <= transformedText.length(); ++end) {
+ assertCharSequence(transformedText.subSequence(start, end),
+ expected.subSequence(start, end));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void transformedText_subSequence_singleLine() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, true, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final CharSequence expected =
+ TEXT.substring(0, offset) + "\uFFFD" + TEXT.substring(offset);
+
+ for (int start = 0; start < transformedText.length(); ++start) {
+ for (int end = start; end <= transformedText.length(); ++end) {
+ assertCharSequence(transformedText.subSequence(start, end),
+ expected.subSequence(start, end));
+ }
+ }
+ }
+ }
+
+ @Test
+ public void transformedText_toString() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, false, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final String expected =
+ TEXT.substring(0, offset) + "\n\n" + TEXT.substring(offset);
+
+ assertThat(transformedText.toString()).isEqualTo(expected);
+ }
+ }
+
+ @Test
+ public void transformedText_toString_singleLine() {
+ for (int offset = 0; offset < TEXT.length(); ++offset) {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(offset, true, null);
+ final CharSequence transformedText =
+ transformationMethod.getTransformation(TEXT, sView);
+ final String expected =
+ TEXT.substring(0, offset) + "\uFFFD" + TEXT.substring(offset);
+
+ assertThat(transformedText.toString()).isEqualTo(expected);
+ }
+ }
+
+
+ @Test
+ public void transformedText_getSpans() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText "abc\n\n def", the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [2, 6)
+ // span3: [6, 7)
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, false, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+
+ // only span1 is in the range of [0, 2).
+ final TestSpan[] spans0to2 = transformedText.getSpans(0, 2, TestSpan.class);
+ assertThat(spans0to2.length).isEqualTo(1);
+ assertThat(spans0to2[0]).isEqualTo(span1);
+
+ // span1 and span2 are in the range of [1, 6).
+ final TestSpan[] spans1to6 = transformedText.getSpans(1, 6, TestSpan.class);
+ assertThat(spans1to6.length).isEqualTo(2);
+ assertThat(spans1to6[0]).isEqualTo(span1);
+ assertThat(spans1to6[1]).isEqualTo(span2);
+
+ // only span2 is in the range of [4, 6).
+ final TestSpan[] spans4to6 = transformedText.getSpans(4, 6, TestSpan.class);
+ assertThat(spans4to6.length).isEqualTo(1);
+ assertThat(spans4to6[0]).isEqualTo(span2);
+
+ // span2 and span3 are in the range of [4, 7).
+ final TestSpan[] spans4to7 = transformedText.getSpans(4, 7, TestSpan.class);
+ assertThat(spans4to7.length).isEqualTo(2);
+ assertThat(spans4to7[0]).isEqualTo(span2);
+ assertThat(spans4to7[1]).isEqualTo(span3);
+
+ // only span3 is in the range of [6, 7).
+ final TestSpan[] spans6to7 = transformedText.getSpans(6, 7, TestSpan.class);
+ assertThat(spans6to7.length).isEqualTo(1);
+ assertThat(spans6to7[0]).isEqualTo(span3);
+
+ // there is no span in the range of [7, 9).
+ final TestSpan[] spans7to9 = transformedText.getSpans(7, 9, TestSpan.class);
+ assertThat(spans7to9.length).isEqualTo(0);
+ }
+
+ @Test
+ public void transformedText_getSpans_singleLine() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText, the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [2, 5)
+ // span3: [5, 6)
+ // There should also be a ReplacementSpan in the range [3, 4).
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, true, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+
+ // only span1 is in the range of [0, 2).
+ final TestSpan[] spans0to2 = transformedText.getSpans(0, 2, TestSpan.class);
+ assertThat(spans0to2.length).isEqualTo(1);
+ assertThat(spans0to2[0]).isEqualTo(span1);
+
+ // span1 and span2 are in the range of [1, 5).
+ final TestSpan[] spans1to4 = transformedText.getSpans(1, 4, TestSpan.class);
+ assertThat(spans1to4.length).isEqualTo(2);
+ assertThat(spans1to4[0]).isEqualTo(span1);
+ assertThat(spans1to4[1]).isEqualTo(span2);
+
+ // only span2 is in the range of [3, 5).
+ final TestSpan[] spans3to5 = transformedText.getSpans(3, 5, TestSpan.class);
+ assertThat(spans3to5.length).isEqualTo(1);
+ assertThat(spans3to5[0]).isEqualTo(span2);
+
+ // span2 and span3 are in the range of [3, 6).
+ final TestSpan[] spans3to6 = transformedText.getSpans(3, 6, TestSpan.class);
+ assertThat(spans3to6.length).isEqualTo(2);
+ assertThat(spans3to6[0]).isEqualTo(span2);
+ assertThat(spans3to6[1]).isEqualTo(span3);
+
+ // only span3 is in the range of [5, 6).
+ final TestSpan[] spans5to6 = transformedText.getSpans(5, 6, TestSpan.class);
+ assertThat(spans5to6.length).isEqualTo(1);
+ assertThat(spans5to6[0]).isEqualTo(span3);
+
+ // there is no span in the range of [6, 8)
+ final TestSpan[] spans6to8 = transformedText.getSpans(6, 8, TestSpan.class);
+ assertThat(spans6to8.length).isEqualTo(0);
+
+ // When it's singleLine, there should be a ReplacementSpan in the range [3, 4)
+ final ReplacementSpan[] replacementSpans3to4 =
+ transformedText.getSpans(3, 4, ReplacementSpan.class);
+ assertThat(replacementSpans3to4.length).isEqualTo(1);
+
+ final ReplacementSpan[] replacementSpans0to3 =
+ transformedText.getSpans(0, 3, ReplacementSpan.class);
+ assertThat(replacementSpans0to3.length).isEqualTo(0);
+
+ final ReplacementSpan[] replacementSpans4to8 =
+ transformedText.getSpans(4, 8, ReplacementSpan.class);
+ assertThat(replacementSpans4to8.length).isEqualTo(0);
+ }
+
+ @Test
+ public void transformedText_getSpanStartAndEnd() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText, the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [2, 6)
+ // span3: [6, 7)
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, false, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+
+ assertThat(transformedText.getSpanStart(span1)).isEqualTo(0);
+ assertThat(transformedText.getSpanEnd(span1)).isEqualTo(3);
+
+ assertThat(transformedText.getSpanStart(span2)).isEqualTo(2);
+ assertThat(transformedText.getSpanEnd(span2)).isEqualTo(6);
+
+ assertThat(transformedText.getSpanStart(span3)).isEqualTo(6);
+ assertThat(transformedText.getSpanEnd(span3)).isEqualTo(7);
+ }
+
+ @Test
+ public void transformedText_getSpanStartAndEnd_singleLine() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText, the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [2, 5)
+ // span3: [5, 6)
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, true, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+
+ assertThat(transformedText.getSpanStart(span1)).isEqualTo(0);
+ assertThat(transformedText.getSpanEnd(span1)).isEqualTo(3);
+
+ assertThat(transformedText.getSpanStart(span2)).isEqualTo(2);
+ assertThat(transformedText.getSpanEnd(span2)).isEqualTo(5);
+
+ assertThat(transformedText.getSpanStart(span3)).isEqualTo(5);
+ assertThat(transformedText.getSpanEnd(span3)).isEqualTo(6);
+
+ final ReplacementSpan[] replacementSpans =
+ transformedText.getSpans(0, 8, ReplacementSpan.class);
+ assertThat(transformedText.getSpanStart(replacementSpans[0])).isEqualTo(3);
+ assertThat(transformedText.getSpanEnd(replacementSpans[0])).isEqualTo(4);
+ }
+
+ @Test
+ public void transformedText_getSpanFlag() {
+ transformedText_getSpanFlag(false);
+ }
+
+ @Test
+ public void transformedText_getSpanFlag_singleLine() {
+ transformedText_getSpanFlag(true);
+ }
+
+ public void transformedText_getSpanFlag(boolean singleLine) {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+ text.setSpan(span1, 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 2, 4, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, singleLine, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+
+ assertThat(transformedText.getSpanFlags(span1)).isEqualTo(Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ assertThat(transformedText.getSpanFlags(span2)).isEqualTo(Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
+ assertThat(transformedText.getSpanFlags(span3)).isEqualTo(Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ }
+
+ @Test
+ public void transformedText_nextSpanTransition() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 1, 4, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText, the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [1, 6)
+ // span3: [6, 7)
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, false, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+ final int[] expectedTransitions = new int[] { 0, 1, 3, 6, 7 };
+ assertNextSpanTransition(transformedText, expectedTransitions, TestSpan.class);
+ }
+
+ @Test
+ public void transformedText_nextSpanTransition_singleLine() {
+ final SpannableString text = new SpannableString(TEXT);
+ final TestSpan span1 = new TestSpan();
+ final TestSpan span2 = new TestSpan();
+ final TestSpan span3 = new TestSpan();
+
+
+ text.setSpan(span1, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text.setSpan(span2, 1, 4, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
+ text.setSpan(span3, 4, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ // In the transformedText, the new ranges of the spans are:
+ // span1: [0, 3)
+ // span2: [1, 5)
+ // span3: [5, 6)
+ // there is also a ReplacementSpan at range [3, 4)
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, true, null);
+ final Spanned transformedText =
+ (Spanned) transformationMethod.getTransformation(text, sView);
+ final int[] expectedTransitions = new int[] { 0, 1, 3, 4, 5, 6 };
+ assertNextSpanTransition(transformedText, expectedTransitions, Object.class);
+ }
+
+ @Test
+ public void transformedText_originalToTransformed() {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(2, false, null);
+ final OffsetMapping transformedText =
+ (OffsetMapping) transformationMethod.getTransformation(TEXT, sView);
+
+ // "abc def" is transformed to "ab\n\nc def".
+ final int[] mappedCharacterOffsets = new int[] { 0, 1, 4, 5, 6, 7, 8 };
+ assertOriginalToTransformed(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCharacterOffsets);
+
+ // "abc def" is transformed to "ab\n\nc def".
+ // the cursor before 'c' is mapped to index position before "\n\n".
+ final int[] mappedCursorOffsets = new int[] { 0, 1, 2, 5, 6, 7, 8 };
+ assertOriginalToTransformed(transformedText, OffsetMapping.MAP_STRATEGY_CURSOR,
+ mappedCursorOffsets);
+ }
+
+ @Test
+ public void transformedText_originalToTransformed_singleLine() {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(2, true, null);
+ final OffsetMapping transformedText =
+ (OffsetMapping) transformationMethod.getTransformation(TEXT, sView);
+
+ // "abc def" is transformed to "ab\uFFFDc def".
+ final int[] mappedCharacterOffsets = new int[] { 0, 1, 3, 4, 5, 6, 7 };
+ assertOriginalToTransformed(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCharacterOffsets);
+
+ // "abc def" is transformed to "ab\uFFFDc def".
+ // the cursor before 'c' is mapped to index position before "\uFFFD".
+ final int[] mappedCursorOffsets = new int[] { 0, 1, 3, 4, 5, 6, 7 };
+ assertOriginalToTransformed(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCursorOffsets);
+ }
+
+ @Test
+ public void transformedText_transformedToOriginal() {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(2, false, null);
+ final OffsetMapping transformedText =
+ (OffsetMapping) transformationMethod.getTransformation(TEXT, sView);
+
+ // "abc def" is transformed to "ab\n\nc def".
+ // the two '\n' characters have no corresponding character; map them to 'c'.
+ final int[] mappedCharacterOffsets = new int[] { 0, 1, 2, 2, 2, 3, 4, 5, 6 };
+ assertTransformedToOriginal(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCharacterOffsets);
+
+ // offset 2 and 3 (cursor positions before the two '\n' characters) are mapped to index 2
+ // (cursor position before 'c' in the original text)
+ final int[] mappedCursorOffsets = new int[] { 0, 1, 2, 2, 2, 3, 4, 5, 6 };
+ assertTransformedToOriginal(transformedText, OffsetMapping.MAP_STRATEGY_CURSOR,
+ mappedCursorOffsets);
+ }
+
+ @Test
+ public void transformedText_transformedToOriginal_singleLine() {
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(2, true, null);
+ final OffsetMapping transformedText =
+ (OffsetMapping) transformationMethod.getTransformation(TEXT, sView);
+
+ // "abc def" is transformed to "ab\uFFFDc def".
+ // '\uFFFD' has no corresponding character; map it to 'c'.
+ final int[] mappedCharacterOffsets = new int[] { 0, 1, 2, 2, 3, 4, 5, 6 };
+ assertTransformedToOriginal(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCharacterOffsets);
+
+ // offset 2 (cursor positions before '\uFFFD') is mapped to index 2 (cursor position before
+ // 'c' in the original text)
+ final int[] mappedCursorOffsets = new int[] { 0, 1, 2, 2, 3, 4, 5, 6 };
+ assertTransformedToOriginal(transformedText, OffsetMapping.MAP_STRATEGY_CHARACTER,
+ mappedCursorOffsets);
+ }
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_insertion() {
+ transformedText_getHighlightStartAndEnd_insertion(false, "\n\n");
+ }
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_insertion_singleLine() {
+ transformedText_getHighlightStartAndEnd_insertion(true, "\uFDDD");
+ }
+
+ public void transformedText_getHighlightStartAndEnd_insertion(boolean singleLine,
+ String placeholder) {
+ final SpannableStringBuilder text = new SpannableStringBuilder(TEXT);
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, singleLine, null);
+ final InsertModeTransformationMethod.TransformedText transformedText =
+ (InsertModeTransformationMethod.TransformedText) transformationMethod
+ .getTransformation(text, sView);
+ // TransformationMethod is set on the original text as a TextWatcher in the TextView.
+ text.setSpan(transformationMethod, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ // note: the placeholder text is also highlighted.
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(3 + placeholder.length());
+
+ // original text is "abcxx def" after insertion.
+ // the placeholder is now inserted at index 5.
+ // the highlight start is still 3.
+ // the highlight end now is 5 + placeholder.length(), including the newly inserted text.
+ text.insert(3, "xx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(5 + placeholder.length());
+
+ // original text is "abcxxvv def" after insertion.
+ // the placeholder is now inserted at index 7.
+ // the highlight start is still 3.
+ // the highlight end now is 7 + placeholder.length(), including the newly inserted text.
+ text.insert(5, "vv");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(7 + placeholder.length());
+
+ // original text is "abzzcxxvv def" after insertion.
+ // the placeholder is now inserted at index 9.
+ // the highlight start is 5, since the insertion happens before the highlight range.
+ // the highlight end now is 9 + placeholder.length().
+ text.insert(2, "zz");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(5);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(9 + placeholder.length());
+
+ // original text is "abzzcxxvv iidef" after insertion.
+ // the placeholder is still inserted at index 9.
+ // the highlight start is still 5, since the insertion happens after the highlight range.
+ // the highlight end now is 9 + placeholder.length().
+ text.insert(10, "ii");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(5);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(9 + placeholder.length());
+
+ }
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_deletion() {
+ transformedText_getHighlightStartAndEnd_deletion(false, "\n\n");
+ }
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_insertion_deletion() {
+ transformedText_getHighlightStartAndEnd_deletion(true, "\uFDDD");
+ }
+
+ public void transformedText_getHighlightStartAndEnd_deletion(boolean singleLine,
+ String placeholder) {
+ final SpannableStringBuilder text = new SpannableStringBuilder(TEXT);
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, singleLine, null);
+ final InsertModeTransformationMethod.TransformedText transformedText =
+ (InsertModeTransformationMethod.TransformedText) transformationMethod
+ .getTransformation(text, sView);
+ // TransformationMethod is set on the original text as a TextWatcher in the TextView.
+ text.setSpan(transformationMethod, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ // note: the placeholder text is also highlighted.
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(3 + placeholder.length());
+
+ // original text is "abcxxxxxx def" after insertion.
+ // the placeholder is now inserted at index 9.
+ // the highlight start is still 3.
+ // the highlight end now is 9 + placeholder.length().
+ text.insert(3, "xxxxxx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(9 + placeholder.length());
+
+ // original text is "abxxxxxx def" after deletion.
+ // the placeholder is now inserted at index 6.
+ // the highlight start is 2, since the deletion happens before the highlight range.
+ // the highlight end now is 8 + placeholder.length().
+ text.delete(2, 3);
+ assertThat(transformedText.getHighlightStart()).isEqualTo(2);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(8 + placeholder.length());
+
+ // original text is "abxxx def" after deletion.
+ // the placeholder is now inserted at index 5.
+ // the highlight start is still 2, since the deletion happens in the highlight range.
+ // the highlight end now is 5 + placeholder.length().
+ text.delete(2, 5);
+ assertThat(transformedText.getHighlightStart()).isEqualTo(2);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(5 + placeholder.length());
+
+ // original text is "abxxx d" after deletion.
+ // the placeholder is now inserted at index 5.
+ // the highlight start is still 2, since the deletion happens after the highlight range.
+ // the highlight end now is still 5 + placeholder.length().
+ text.delete(7, 9);
+ assertThat(transformedText.getHighlightStart()).isEqualTo(2);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(5 + placeholder.length());
+
+ // original text is "af" after deletion.
+ // the placeholder is now inserted at index 1.
+ // the highlight start is 1, since the deletion covers highlight range.
+ // the highlight end is 1 + placeholder.length().
+ text.delete(1, 5);
+ assertThat(transformedText.getHighlightStart()).isEqualTo(1);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(1 + placeholder.length());
+ }
+
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_replace() {
+ transformedText_getHighlightStartAndEnd_replace(false, "\n\n");
+ }
+
+ @Test
+ public void transformedText_getHighlightStartAndEnd_insertion__replace() {
+ transformedText_getHighlightStartAndEnd_replace(true, "\uFDDD");
+ }
+
+ public void transformedText_getHighlightStartAndEnd_replace(boolean singleLine,
+ String placeholder) {
+ final SpannableStringBuilder text = new SpannableStringBuilder(TEXT);
+ final InsertModeTransformationMethod transformationMethod =
+ new InsertModeTransformationMethod(3, singleLine, null);
+ final InsertModeTransformationMethod.TransformedText transformedText =
+ (InsertModeTransformationMethod.TransformedText) transformationMethod
+ .getTransformation(text, sView);
+ // TransformationMethod is set on the original text as a TextWatcher in the TextView.
+ text.setSpan(transformationMethod, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+
+ // note: the placeholder text is also highlighted.
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(3 + placeholder.length());
+
+ // original text is "abcxxxxxx def" after insertion.
+ // the placeholder is now inserted at index 9.
+ // the highlight start is still 3.
+ // the highlight end now is 9 + placeholder.length().
+ text.insert(3, "xxxxxx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(3);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(9 + placeholder.length());
+
+ // original text is "abvvxxxxxx def" after replace.
+ // the replacement happens before the highlight range; highlight range is offset by 1
+ // the placeholder is now inserted at index 10,
+ // the highlight start is 4.
+ // the highlight end is 10 + placeholder.length().
+ text.replace(2, 3, "vv");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(4);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(10 + placeholder.length());
+
+ // original text is "abvvxxx def" after replace.
+ // the replacement happens in the highlight range; highlight end is offset by -3
+ // the placeholder is now inserted at index 7,
+ // the highlight start is still 4.
+ // the highlight end is 7 + placeholder.length().
+ text.replace(5, 9, "x");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(4);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(7 + placeholder.length());
+
+ // original text is "abvvxxxvvv" after replace.
+ // the replacement happens after the highlight range; highlight is not changed
+ // the placeholder is now inserted at index 7,
+ // the highlight start is still 4.
+ // the highlight end is 7 + placeholder.length().
+ text.replace(7, 11, "vvv");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(4);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(7 + placeholder.length());
+
+ // original text is "abxxxxvvv" after replace.
+ // the replacement happens covers the highlight start; highlight start extends to the
+ // replacement start; highlight end is offset by -1
+ // the placeholder is now inserted at index 6,
+ // the highlight start is 2.
+ // the highlight end is 6 + placeholder.length().
+ text.replace(2, 5, "xx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(2);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(6 + placeholder.length());
+
+ // original text is "abxxxxxvv" after replace.
+ // the replacement happens covers the highlight end; highlight end extends to the
+ // replacement end; highlight start stays the same
+ // the placeholder is now inserted at index 7,
+ // the highlight start is 2.
+ // the highlight end is 7 + placeholder.length().
+ text.replace(5, 7, "xx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(2);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(7 + placeholder.length());
+
+ // original text is "axxv" after replace.
+ // the replacement happens covers the highlight range; highlight start is set to the
+ // replacement start; highlight end is set to the replacement end
+ // the placeholder is now inserted at index 3,
+ // the highlight start is 1.
+ // the highlight end is 3 + placeholder.length().
+ text.replace(1, 8, "xx");
+ assertThat(transformedText.getHighlightStart()).isEqualTo(1);
+ assertThat(transformedText.getHighlightEnd()).isEqualTo(3 + placeholder.length());
+ }
+
+ private static <T> void assertNextSpanTransition(Spanned spanned, int[] transitions,
+ Class<T> type) {
+ int currentTransition = 0;
+ for (int transition : transitions) {
+ assertThat(currentTransition).isEqualTo(transition);
+ currentTransition =
+ spanned.nextSpanTransition(currentTransition, spanned.length(), type);
+ }
+
+ // Make sure there is no transition after the currentTransition.
+ assertThat(currentTransition).isEqualTo(spanned.length());
+ }
+
+ private static void assertCharSequence(CharSequence actual, CharSequence expected) {
+ assertThat(actual.length()).isEqualTo(expected.length());
+ for (int index = 0; index < actual.length(); ++index) {
+ assertThat(actual.charAt(index)).isEqualTo(expected.charAt(index));
+ }
+ }
+
+ private static void assertOriginalToTransformed(OffsetMapping transformedText, int strategy,
+ int[] expected) {
+ for (int offset = 0; offset < expected.length; ++offset) {
+ assertThat(transformedText.originalToTransformed(offset, strategy))
+ .isEqualTo(expected[offset]);
+ }
+ }
+
+ private static void assertTransformedToOriginal(OffsetMapping transformedText, int strategy,
+ int[] expected) {
+ for (int offset = 0; offset < expected.length; ++offset) {
+ assertThat(transformedText.transformedToOriginal(offset, strategy))
+ .isEqualTo(expected[offset]);
+ }
+ }
+
+ private static class TestSpan { }
+}
diff --git a/core/tests/coretests/src/android/view/inputmethod/ParcelableHandwritingGestureTest.java b/core/tests/coretests/src/android/view/inputmethod/ParcelableHandwritingGestureTest.java
index 79aeaa3..90f7d06 100644
--- a/core/tests/coretests/src/android/view/inputmethod/ParcelableHandwritingGestureTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/ParcelableHandwritingGestureTest.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.os.CancellationSignal;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -86,6 +87,14 @@
}
@Test
+ public void testInsertModeGesture() {
+ verifyEqualityAfterUnparcel(new InsertModeGesture.Builder()
+ .setInsertionPoint(new PointF(1, 1)).setFallbackText("")
+ .setCancellationSignal(new CancellationSignal())
+ .build());
+ }
+
+ @Test
public void testDeleteGestureGesture() {
verifyEqualityAfterUnparcel(new DeleteGesture.Builder()
.setGranularity(HandwritingGesture.GRANULARITY_WORD)
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index bbf9f3c..31c5a76 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -324,7 +324,9 @@
RemoteViews nested = new RemoteViews(mPackage, R.layout.remote_views_text);
nested.setOnClickPendingIntent(
R.id.text,
- PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ PendingIntent.getActivity(mContext, 0,
+ new Intent().setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_MUTABLE)
);
RemoteViews listItem = new RemoteViews(mPackage, R.layout.remote_view_host);
@@ -341,7 +343,9 @@
RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
inner.setOnClickPendingIntent(
R.id.text,
- PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ PendingIntent.getActivity(mContext, 0,
+ new Intent().setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_MUTABLE)
);
RemoteViews listItem = new RemoteViews(inner, inner);
@@ -357,7 +361,9 @@
RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
inner.setOnClickPendingIntent(
R.id.text,
- PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ PendingIntent.getActivity(mContext, 0,
+ new Intent().setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_MUTABLE)
);
RemoteViews listItem = new RemoteViews(
@@ -559,7 +565,9 @@
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 1; i < 10; i++) {
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
- new Intent("android.widget.RemoteViewsTest_" + i), PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ new Intent("android.widget.RemoteViewsTest_" + i)
+ .setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
views.setOnClickPendingIntent(i, pi);
}
try {
@@ -575,7 +583,8 @@
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
- new Intent("test"), PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ new Intent("test").setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
views.setOnClickPendingIntent(1, pi);
RemoteViews withCookie = parcelAndRecreateWithPendingIntentCookie(views, whitelistToken);
@@ -606,8 +615,9 @@
public void sharedElement_pendingIntent_notifyParent() throws Exception {
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
- new Intent("android.widget.RemoteViewsTest_shared_element"),
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ new Intent("android.widget.RemoteViewsTest_shared_element")
+ .setPackage(mContext.getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
views.setOnClickResponse(R.id.image, RemoteViews.RemoteResponse.fromPendingIntent(pi)
.addSharedElement(0, "e0")
.addSharedElement(1, "e1")
diff --git a/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java b/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java
index 3e640c1..bdf42ac 100644
--- a/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/AbstractResolverComparatorTest.java
@@ -18,6 +18,7 @@
import static junit.framework.Assert.assertEquals;
+import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +28,10 @@
import androidx.test.InstrumentationRegistry;
+import com.android.internal.app.chooser.TargetInfo;
+
+import com.google.android.collect.Lists;
+
import org.junit.Test;
import java.util.List;
@@ -96,7 +101,8 @@
Intent intent = new Intent();
AbstractResolverComparator testComparator =
- new AbstractResolverComparator(context, intent) {
+ new AbstractResolverComparator(context, intent,
+ Lists.newArrayList(context.getUser())) {
@Override
int compare(ResolveInfo lhs, ResolveInfo rhs) {
@@ -109,7 +115,7 @@
void doCompute(List<ResolverActivity.ResolvedComponentInfo> targets) {}
@Override
- float getScore(ComponentName name) {
+ float getScore(TargetInfo targetInfo) {
return 0;
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
index eead4ed..5469843 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java
@@ -29,7 +29,6 @@
import android.util.Pair;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
-import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
import com.android.internal.app.chooser.TargetInfo;
import com.android.internal.logging.MetricsLogger;
@@ -71,13 +70,14 @@
public int alternateProfileSetting;
public Resources resources;
public UserHandle workProfileUserHandle;
+ public UserHandle cloneProfileUserHandle;
+ public UserHandle tabOwnerUserHandleForLaunch;
public boolean hasCrossProfileIntents;
public boolean isQuietModeEnabled;
public boolean isWorkProfileUserRunning;
public boolean isWorkProfileUserUnlocked;
public Integer myUserId;
public QuietModeManager mQuietModeManager;
- public MyUserIdProvider mMyUserIdProvider;
public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
public PackageManager packageManager;
@@ -98,6 +98,8 @@
alternateProfileSetting = 0;
resources = null;
workProfileUserHandle = null;
+ cloneProfileUserHandle = null;
+ tabOwnerUserHandleForLaunch = null;
hasCrossProfileIntents = true;
isQuietModeEnabled = false;
isWorkProfileUserRunning = true;
@@ -126,13 +128,6 @@
}
};
- mMyUserIdProvider = new MyUserIdProvider() {
- @Override
- public int getMyUserId() {
- return myUserId != null ? myUserId : UserHandle.myUserId();
- }
- };
-
mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
.thenAnswer(invocation -> hasCrossProfileIntents);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index d656678..c06df94 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -143,7 +143,8 @@
* `Parameterized` runner.
* --------
*/
-
+ private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getUser();
private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
pm -> {
@@ -472,7 +473,7 @@
List<ResolvedComponentInfo> infosToStack = new ArrayList<>();
for (int i = 0; i < 4; i++) {
ResolveInfo resolveInfo = ResolverDataProvider.createResolveInfo(i,
- UserHandle.USER_CURRENT);
+ UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
resolveInfo.activityInfo.applicationInfo.name = appName;
resolveInfo.activityInfo.applicationInfo.packageName = packageName;
resolveInfo.activityInfo.packageName = packageName;
@@ -544,13 +545,17 @@
return true;
};
ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
+ DisplayResolveInfo testDri =
+ activity.createTestDisplayResolveInfo(sendIntent, toChoose, "testLabel", "testInfo",
+ sendIntent,/* resolveInfoPresentationGetter */ null);
onView(withText(toChoose.activityInfo.name))
.perform(click());
waitForIdle();
verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
- .updateChooserCounts(Mockito.anyString(), anyInt(), Mockito.anyString());
+ .updateChooserCounts(Mockito.anyString(), any(UserHandle.class),
+ Mockito.anyString());
verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1))
- .updateModel(toChoose.activityInfo.getComponentName());
+ .updateModel(testDri);
assertThat(activity.getIsSelected(), is(true));
}
@@ -1329,7 +1334,11 @@
final DisplayResolveInfo testDri =
activity.createTestDisplayResolveInfo(sendIntent,
- ResolverDataProvider.createResolveInfo(3, 0), "testLabel", "testInfo", sendIntent,
+ ResolverDataProvider.createResolveInfo(
+ 3, 0, PERSONAL_USER_HANDLE),
+ "testLabel",
+ "testInfo",
+ sendIntent,
/* resolveInfoPresentationGetter */ null);
final ChooserListAdapter adapter = activity.getAdapter();
@@ -1450,7 +1459,8 @@
ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
+ PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -1528,7 +1538,8 @@
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
+ PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -1606,7 +1617,8 @@
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
+ PERSONAL_USER_HANDLE);
// Start activity
final ChooserActivity activity =
@@ -1679,7 +1691,8 @@
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
+ PERSONAL_USER_HANDLE);
// Start activity
final ChooserActivity activity =
@@ -1791,7 +1804,8 @@
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0,
+ PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -2187,7 +2201,8 @@
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
- ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+ ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
+ PERSONAL_USER_HANDLE);
ChooserActivityOverrideData
.getInstance()
@@ -2721,7 +2736,7 @@
new Intent[] {new Intent("action.fake")});
ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(0,
- UserHandle.USER_CURRENT);
+ UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
when(
ChooserActivityOverrideData
.getInstance()
@@ -2886,6 +2901,53 @@
assertEquals(3, wrapper.getWorkListAdapter().getCount());
}
+ @Test
+ public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+ List<ResolvedComponentInfo> resolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ ChooserActivityOverrideData.getInstance().cloneProfileUserHandle);
+ when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class)))
+ .thenReturn(new ArrayList<>(resolvedComponentInfos));
+ Intent sendIntent = createSendTextIntent();
+
+ final IChooserWrapper activity = (IChooserWrapper) mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, "personalProfileTest"));
+ waitForIdle();
+
+ assertThat(activity.getPersonalListAdapter().getUserHandle(), is(PERSONAL_USER_HANDLE));
+ assertThat(activity.getAdapter().getCount(), is(3));
+ }
+
+ @Test
+ public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ markCloneProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsForTest(3);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
+ 4);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendTextIntent();
+ sendIntent.setType(TEST_MIME_TYPE);
+
+
+ final IChooserWrapper activity = (IChooserWrapper)
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "multi tab test"));
+ waitForIdle();
+
+ assertThat(activity.getCurrentUserHandle(), is(PERSONAL_USER_HANDLE));
+ }
+
private Intent createChooserIntent(Intent intent, Intent[] initialIntents) {
Intent chooserIntent = new Intent();
chooserIntent.setAction(Intent.ACTION_CHOOSER);
@@ -2906,6 +2968,7 @@
ri.activityInfo.packageName = "fake.package.name";
ri.activityInfo.applicationInfo = new ApplicationInfo();
ri.activityInfo.applicationInfo.packageName = "fake.package.name";
+ ri.userHandle = UserHandle.CURRENT;
return ri;
}
@@ -2967,7 +3030,23 @@
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, PERSONAL_USER_HANDLE));
+ }
+ return infoList;
+ }
+
+ private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
+ int numberOfResults,
+ UserHandle resolvedForPersonalUser,
+ UserHandle resolvedForClonedUser) {
+ List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+ for (int i = 0; i < 1; i++) {
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ resolvedForPersonalUser));
+ }
+ for (int i = 1; i < numberOfResults; i++) {
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ resolvedForClonedUser));
}
return infoList;
}
@@ -2977,9 +3056,11 @@
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
+ PERSONAL_USER_HANDLE));
} else {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ PERSONAL_USER_HANDLE));
}
}
return infoList;
@@ -2991,9 +3072,11 @@
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(
- ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+ ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
+ PERSONAL_USER_HANDLE));
} else {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ PERSONAL_USER_HANDLE));
}
}
return infoList;
@@ -3003,7 +3086,8 @@
int numberOfResults, int userId) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
+ PERSONAL_USER_HANDLE));
}
return infoList;
}
@@ -3097,6 +3181,10 @@
ChooserActivityOverrideData.getInstance().workProfileUserHandle = UserHandle.of(10);
}
+ private void markCloneProfileUserAvailable() {
+ ChooserActivityOverrideData.getInstance().cloneProfileUserHandle = UserHandle.of(11);
+ }
+
private void setupResolverControllers(
List<ResolvedComponentInfo> personalResolvedComponentInfos,
List<ResolvedComponentInfo> workResolvedComponentInfos) {
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityWorkProfileTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityWorkProfileTest.java
index b6ea9dd..db69cf2 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityWorkProfileTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityWorkProfileTest.java
@@ -49,8 +49,8 @@
import androidx.test.rule.ActivityTestRule;
import com.android.internal.R;
-import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.app.ChooserActivityWorkProfileTest.TestCase.Tab;
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import junit.framework.AssertionFailedError;
@@ -93,7 +93,7 @@
public void testBlocker() {
setUpPersonalAndWorkComponentInfos();
sOverrides.hasCrossProfileIntents = mTestCase.hasCrossProfileIntents();
- sOverrides.myUserId = mTestCase.getMyUserHandle().getIdentifier();
+ sOverrides.tabOwnerUserHandleForLaunch = mTestCase.getMyUserHandle();
launchActivity(mTestCase.getIsSendAction());
switchToTab(mTestCase.getTab());
@@ -238,19 +238,21 @@
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
- int numberOfResults, int userId) {
+ int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(
- ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+ ResolverDataProvider
+ .createResolvedComponentInfoWithOtherId(i, userId, resolvedForUser));
}
return infoList;
}
- private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+ private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
+ UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
return infoList;
}
@@ -262,9 +264,9 @@
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3,
- /* userId */ WORK_USER_HANDLE.getIdentifier());
+ /* userId */ WORK_USER_HANDLE.getIdentifier(), PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(workProfileTargets);
+ createResolvedComponentsForTest(workProfileTargets, WORK_USER_HANDLE);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 5dc0c8b..d7a8b3a 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -16,10 +16,6 @@
package com.android.internal.app;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
@@ -34,12 +30,12 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Bundle;
import android.os.UserHandle;
import android.util.Pair;
import android.util.Size;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
-import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.TargetInfo;
@@ -132,14 +128,6 @@
}
@Override
- protected MyUserIdProvider createMyUserIdProvider() {
- if (sOverrides.mMyUserIdProvider != null) {
- return sOverrides.mMyUserIdProvider;
- }
- return super.createMyUserIdProvider();
- }
-
- @Override
protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
if (sOverrides.mCrossProfileIntentsChecker != null) {
return sOverrides.mCrossProfileIntentsChecker;
@@ -155,13 +143,15 @@
return super.createQuietModeManager();
}
+ // TODO: Remove this and override safelyStartActivityInternal() instead.
@Override
- public void safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti) {
+ public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
+ @Nullable Bundle options) {
if (sOverrides.onSafelyStartCallback != null &&
sOverrides.onSafelyStartCallback.apply(cti)) {
return;
}
- super.safelyStartActivity(cti);
+ super.safelyStartActivityAsUser(cti, user, options);
}
@Override
@@ -253,6 +243,14 @@
}
@Override
+ protected UserHandle getTabOwnerUserHandleForLaunch() {
+ if (sOverrides.tabOwnerUserHandleForLaunch == null) {
+ return super.getTabOwnerUserHandleForLaunch();
+ }
+ return sOverrides.tabOwnerUserHandleForLaunch;
+ }
+
+ @Override
public Context createContextAsUser(UserHandle user, int flags) {
// return the current context as a work profile doesn't really exist in these tests
return getApplicationContext();
diff --git a/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java b/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java
index fbbe57c..573135ffa 100644
--- a/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java
+++ b/core/tests/coretests/src/com/android/internal/app/FakeResolverComparatorModel.java
@@ -19,6 +19,8 @@
import android.content.ComponentName;
import android.content.pm.ResolveInfo;
+import com.android.internal.app.chooser.TargetInfo;
+
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -45,14 +47,15 @@
}
@Override
- public float getScore(ComponentName name) {
+ public float getScore(TargetInfo targetInfo) {
return 0.0f; // Models are not required to provide numerical scores.
}
@Override
- public void notifyOnTargetSelected(ComponentName componentName) {
+ public void notifyOnTargetSelected(TargetInfo targetInfo) {
System.out.println(
- "User selected " + componentName + " under model " + System.identityHashCode(this));
+ "User selected " + targetInfo.getResolvedComponentName() + " under model "
+ + System.identityHashCode(this));
}
private FakeResolverComparatorModel(Comparator<ResolveInfo> comparator) {
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 92c05b0..b82bc16 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -79,6 +79,9 @@
*/
@RunWith(AndroidJUnit4.class)
public class ResolverActivityTest {
+
+ private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getUser();
@Rule
public ActivityTestRule<ResolverWrapperActivity> mActivityRule =
new ActivityTestRule<>(ResolverWrapperActivity.class, false,
@@ -92,7 +95,8 @@
@Test
public void twoOptionsAndUserSelectsOne() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
+ PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -124,7 +128,8 @@
@Test
public void setMaxHeight() throws Exception {
Intent sendIntent = createSendImageIntent();
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
+ PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -169,7 +174,8 @@
@Test
public void setShowAtTopToTrue() throws Exception {
Intent sendIntent = createSendImageIntent();
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
+ PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -201,7 +207,8 @@
@Test
public void hasLastChosenActivity() throws Exception {
Intent sendIntent = createSendImageIntent();
- List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
+ PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -234,10 +241,12 @@
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
- setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
Intent sendIntent = createSendImageIntent();
@@ -255,7 +264,8 @@
};
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
- createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10);
+ createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10,
+ PERSONAL_USER_HANDLE);
// We pick the first one as there is another one in the work profile side
onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
.perform(click());
@@ -272,7 +282,7 @@
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3);
+ createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -298,7 +308,7 @@
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
- createResolvedComponentsForTestWithOtherProfile(2);
+ createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
.perform(click());
@@ -317,7 +327,7 @@
// chosen activity.
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3);
+ createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -345,7 +355,7 @@
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
- createResolvedComponentsForTestWithOtherProfile(2);
+ createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
.perform(click());
@@ -428,12 +438,14 @@
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId = */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId = */ 10,
+ PERSONAL_USER_HANDLE);
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos,
new ArrayList<>(workResolvedComponentInfos));
Intent sendIntent = createSendImageIntent();
- markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -448,11 +460,13 @@
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
- markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -467,11 +481,12 @@
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
+ markWorkProfileUserAvailable();
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
- markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -487,8 +502,10 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -507,8 +524,10 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
ResolveInfo[] chosen = new ResolveInfo[1];
@@ -539,8 +558,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(1);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -559,8 +579,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(1);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createOpenWebsiteIntent();
@@ -578,8 +599,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(1);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createOpenWebsiteIntent();
@@ -605,8 +627,10 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId= */ 10);
- List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId= */ 10,
+ PERSONAL_USER_HANDLE);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
ResolveInfo[] chosen = new ResolveInfo[1];
@@ -639,9 +663,11 @@
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(workProfileTargets);
+ createResolvedComponentsForTest(workProfileTargets,
+ sOverrides.workProfileUserHandle);
sOverrides.hasCrossProfileIntents = false;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -665,9 +691,11 @@
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
+ createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(workProfileTargets);
+ createResolvedComponentsForTest(workProfileTargets,
+ sOverrides.workProfileUserHandle);
sOverrides.isQuietModeEnabled = true;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -690,9 +718,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(3);
+ createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(0);
+ createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -714,9 +742,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(3);
+ createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(0);
+ createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -739,9 +767,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(1);
+ createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(1);
+ createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
// Personal profile only has a browser
personalResolvedComponentInfos.get(0).getResolveInfoAt(0).handleAllWebDataURI = true;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
@@ -758,9 +786,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(0);
+ createResolvedComponentsForTest(0, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(1);
+ createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -787,9 +815,9 @@
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(3);
+ createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(0);
+ createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -810,7 +838,8 @@
public void testAutolaunch_singleTarget_withWorkProfileAndTabbedViewOff_noAutolaunch() {
ResolverActivity.ENABLE_TABBED_VIEW = false;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
+ createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -835,7 +864,7 @@
public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
ResolverActivity.ENABLE_TABBED_VIEW = false;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTest(1);
+ createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -863,9 +892,11 @@
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
- createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
+ createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
+ PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(workProfileTargets);
+ createResolvedComponentsForTest(workProfileTargets,
+ sOverrides.workProfileUserHandle);
sOverrides.hasCrossProfileIntents = false;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -892,7 +923,7 @@
// chosen activity.
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
- createResolvedComponentsForTest(2);
+ createResolvedComponentsForTest(2, PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -911,6 +942,193 @@
assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
}
+ @Test
+ public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+ List<ResolvedComponentInfo> resolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+
+ assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
+ assertThat(activity.getAdapter().getCount(), is(3));
+ }
+
+ @Test
+ public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+ List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
+ sOverrides.workProfileUserHandle);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+
+ assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
+ assertThat(activity.getAdapter().getCount(), is(3));
+ }
+
+ @Test
+ public void testClonedProfilePresent_layoutWithDefault_neverShown() throws Exception {
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+ Intent sendIntent = createSendImageIntent();
+ List<ResolvedComponentInfo> resolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 2,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ when(sOverrides.resolverListController.getLastChosen())
+ .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
+ waitForIdle();
+
+ assertThat(activity.getAdapter().hasFilteredItem(), is(false));
+ assertThat(activity.getAdapter().getCount(), is(2));
+ assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
+ }
+
+ @Test
+ public void testClonedProfilePresent_alwaysButtonDisabled() throws Exception {
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+ Intent sendIntent = createSendImageIntent();
+ List<ResolvedComponentInfo> resolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ when(sOverrides.resolverListController.getLastChosen())
+ .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+
+ // Confirm that the button bar is disabled by default
+ onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
+ onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
+
+ // Make a stable copy of the components as the original list may be modified
+ List<ResolvedComponentInfo> stableCopy =
+ createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
+
+ onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
+ .perform(click());
+
+ onView(withId(R.id.button_once)).check(matches(isEnabled()));
+ onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
+ }
+
+ @Test
+ public void testClonedProfilePresent_personalProfileActivityIsStartedInCorrectUser()
+ throws Exception {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
+ sOverrides.hasCrossProfileIntents = false;
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+ sendIntent.setType("TestType");
+ final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
+ sOverrides.onSafelyStartInternalCallback = userHandle -> {
+ selectedActivityUserHandle[0] = userHandle;
+ return true;
+ };
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+ onView(first(allOf(withText(personalResolvedComponentInfos.get(0)
+ .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
+ .perform(click());
+ onView(withId(R.id.button_once))
+ .perform(click());
+ waitForIdle();
+
+ assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
+ }
+
+ @Test
+ public void testClonedProfilePresent_workProfileActivityIsStartedInCorrectUser()
+ throws Exception {
+ // enable the work tab feature flag
+ ResolverActivity.ENABLE_TABBED_VIEW = true;
+ markWorkProfileUserAvailable();
+ // enable cloneProfile
+ markCloneProfileUserAvailable();
+
+ List<ResolvedComponentInfo> personalResolvedComponentInfos =
+ createResolvedComponentsWithCloneProfileForTest(
+ 3,
+ PERSONAL_USER_HANDLE,
+ sOverrides.cloneProfileUserHandle);
+ List<ResolvedComponentInfo> workResolvedComponentInfos =
+ createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
+ setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
+ Intent sendIntent = createSendImageIntent();
+ sendIntent.setType("TestType");
+ final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
+ sOverrides.onSafelyStartInternalCallback = userHandle -> {
+ selectedActivityUserHandle[0] = userHandle;
+ return true;
+ };
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ waitForIdle();
+ onView(withText(R.string.resolver_work_tab))
+ .perform(click());
+ waitForIdle();
+ onView(first(allOf(withText(workResolvedComponentInfos.get(0)
+ .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
+ .perform(click());
+ onView(withId(R.id.button_once))
+ .perform(click());
+ waitForIdle();
+
+ assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
+ }
+
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -926,36 +1144,55 @@
return sendIntent;
}
- private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+ private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
+ UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
+ }
+ return infoList;
+ }
+
+ private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
+ int numberOfResults,
+ UserHandle resolvedForPersonalUser,
+ UserHandle resolvedForClonedUser) {
+ List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+ for (int i = 0; i < 1; i++) {
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ resolvedForPersonalUser));
+ }
+ for (int i = 1; i < numberOfResults; i++) {
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
+ resolvedForClonedUser));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
- int numberOfResults) {
+ int numberOfResults, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
+ resolvedForUser));
} else {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
- int numberOfResults, int userId) {
+ int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(
- ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+ ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
+ resolvedForUser));
} else {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
}
return infoList;
@@ -969,6 +1206,10 @@
ResolverWrapperActivity.sOverrides.workProfileUserHandle = UserHandle.of(10);
}
+ private void markCloneProfileUserAvailable() {
+ ResolverWrapperActivity.sOverrides.cloneProfileUserHandle = UserHandle.of(11);
+ }
+
private void setupResolverControllers(
List<ResolvedComponentInfo> personalResolvedComponentInfos,
List<ResolvedComponentInfo> workResolvedComponentInfos) {
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityWorkProfileTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityWorkProfileTest.java
index 4a79f5e..9d16d85 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityWorkProfileTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityWorkProfileTest.java
@@ -92,7 +92,7 @@
public void testBlocker() {
setUpPersonalAndWorkComponentInfos();
sOverrides.hasCrossProfileIntents = mTestCase.hasCrossProfileIntents();
- sOverrides.myUserId = mTestCase.getMyUserHandle().getIdentifier();
+ sOverrides.tabOwnerUserHandleForLaunch = mTestCase.getMyUserHandle();
launchActivity(/* callingUser= */ mTestCase.getExtraCallingUser());
switchToTab(mTestCase.getTab());
@@ -230,19 +230,21 @@
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
- int numberOfResults, int userId) {
+ int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(
- ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+ ResolverDataProvider
+ .createResolvedComponentInfoWithOtherId(i, userId, resolvedForUser));
}
return infoList;
}
- private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
+ private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
+ UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
return infoList;
}
@@ -254,9 +256,9 @@
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3,
- /* userId */ WORK_USER_HANDLE.getIdentifier());
+ /* userId */ WORK_USER_HANDLE.getIdentifier(), PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
- createResolvedComponentsForTest(workProfileTargets);
+ createResolvedComponentsForTest(workProfileTargets, WORK_USER_HANDLE);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
index d7db5f8..55318f3 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
@@ -36,20 +36,24 @@
static private int USER_SOMEONE_ELSE = 10;
- static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfo(int i) {
- return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
- createResolverIntent(i), createResolveInfo(i, UserHandle.USER_CURRENT));
- }
-
- static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i) {
- return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
- createResolverIntent(i), createResolveInfo(i, USER_SOMEONE_ELSE));
+ static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfo(int i,
+ UserHandle resolvedForUser) {
+ return new ResolverActivity.ResolvedComponentInfo(
+ createComponentName(i),
+ createResolverIntent(i),
+ createResolveInfo(i, UserHandle.USER_CURRENT, resolvedForUser));
}
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i,
- int userId) {
+ UserHandle resolvedForUser) {
return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
- createResolverIntent(i), createResolveInfo(i, userId));
+ createResolverIntent(i), createResolveInfo(i, USER_SOMEONE_ELSE, resolvedForUser));
+ }
+
+ static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i,
+ int userId, UserHandle resolvedForUser) {
+ return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
+ createResolverIntent(i), createResolveInfo(i, userId, resolvedForUser));
}
static ComponentName createComponentName(int i) {
@@ -57,10 +61,11 @@
return new ComponentName("foo.bar." + name, name);
}
- static ResolveInfo createResolveInfo(int i, int userId) {
+ static ResolveInfo createResolveInfo(int i, int userId, UserHandle resolvedForUser) {
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.activityInfo = createActivityInfo(i);
resolveInfo.targetUserId = userId;
+ resolveInfo.userHandle = resolvedForUser;
return resolveInfo;
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
index 42593f6..8f6cee3 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -44,6 +44,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -75,6 +76,8 @@
private ResolverListController mController;
private UsageStatsManager mUsm;
+ private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
+ .getInstrumentation().getTargetContext().getUser();
@Before
public void setUp() throws Exception {
@@ -83,6 +86,7 @@
config.locale = Locale.getDefault();
List<ResolveInfo> services = new ArrayList<>();
mUsm = new UsageStatsManager(mMockContext, mMockService);
+ when(mMockContext.createContextAsUser(any(), anyInt())).thenReturn(mMockContext);
when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE)).thenReturn(mUsm);
when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenReturn(services);
when(mMockResources.getConfiguration()).thenReturn(config);
@@ -119,10 +123,11 @@
anyString(), anyInt(), anyString(), any(), anyString());
when(mMockContext.getOpPackageName()).thenReturn(refererPackage);
mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
- refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM);
+ refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM,
+ UserHandle.SYSTEM);
mController.sort(new ArrayList<ResolvedComponentInfo>());
long beforeReport = getCount(mUsm, packageName, action, annotation);
- mController.updateChooserCounts(packageName, UserHandle.USER_CURRENT, action);
+ mController.updateChooserCounts(packageName, UserHandle.SYSTEM, action);
long afterReport = getCount(mUsm, packageName, action, annotation);
assertThat(afterReport, is(beforeReport + 1l));
}
@@ -134,7 +139,8 @@
String refererPackage = "test_referer_package";
List<ResolvedComponentInfo> resolvedComponents = createResolvedComponentsForTest(10);
mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
- refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM);
+ refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM,
+ UserHandle.SYSTEM);
List<ResolvedComponentInfo> topKList = new ArrayList<>(resolvedComponents);
mController.topK(topKList, 5);
List<ResolvedComponentInfo> sortList = new ArrayList<>(topKList);
@@ -157,12 +163,13 @@
public void getResolversForIntent_usesResultsFromPackageManager() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
- infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
+ infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
+ PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
- /* userHandle= */ UserHandle.SYSTEM);
+ /* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -181,12 +188,13 @@
public void getResolversForIntent_shouldGetOnlyDefaultActivitiesTrue_addsFlag() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
- infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
+ infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
+ PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
- /* userHandle= */ UserHandle.SYSTEM);
+ /* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -205,12 +213,13 @@
public void getResolversForIntent_shouldGetOnlyDefaultActivitiesFalse_doesNotAddFlag() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
- infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
+ infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
+ PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
- /* userHandle= */ UserHandle.SYSTEM);
+ /* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -225,6 +234,32 @@
doesNotContainFlag(PackageManager.MATCH_DEFAULT_ONLY), any());
}
+
+ @Test
+ public void testResolveInfoWithNoUserHandle_isNotAddedToResults()
+ throws Exception {
+ List<ResolveInfo> infos = new ArrayList<>();
+ infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
+ PERSONAL_USER_HANDLE));
+ infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT, null));
+ when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
+ any(UserHandle.class))).thenReturn(infos);
+ mController = new ResolverListController(mMockContext, mMockPackageManager,
+ createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
+ /* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
+ List<Intent> intents = new ArrayList<>();
+ intents.add(createActionMainIntent());
+
+ List<ResolverActivity.ResolvedComponentInfo> result = mController
+ .getResolversForIntent(
+ /* shouldGetResolvedFilter= */ true,
+ /* shouldGetActivityMetadata= */ true,
+ /* shouldGetOnlyDefaultActivities= */ false,
+ intents);
+
+ assertThat(result.size(), is(1));
+ }
+
private int containsFlag(int flag) {
return intThat(new FlagMatcher(flag, /* contains= */ true));
}
@@ -308,7 +343,7 @@
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
- infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+ infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, PERSONAL_USER_HANDLE));
}
return infoList;
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index c778dfe..8f6f29d 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.annotation.Nullable;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
@@ -30,7 +31,6 @@
import android.os.UserHandle;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
-import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
import com.android.internal.app.chooser.TargetInfo;
@@ -57,14 +57,6 @@
}
@Override
- protected MyUserIdProvider createMyUserIdProvider() {
- if (sOverrides.mMyUserIdProvider != null) {
- return sOverrides.mMyUserIdProvider;
- }
- return super.createMyUserIdProvider();
- }
-
- @Override
protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
if (sOverrides.mCrossProfileIntentsChecker != null) {
return sOverrides.mCrossProfileIntentsChecker;
@@ -103,13 +95,25 @@
return super.isVoiceInteraction();
}
+ // TODO: Remove this and override safelyStartActivityInternal() instead.
@Override
- public void safelyStartActivity(TargetInfo cti) {
+ public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
+ @Nullable Bundle options) {
if (sOverrides.onSafelyStartCallback != null &&
sOverrides.onSafelyStartCallback.apply(cti)) {
return;
}
- super.safelyStartActivity(cti);
+ super.safelyStartActivityAsUser(cti, user, options);
+ }
+
+ @Override
+ public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
+ @Nullable Bundle options) {
+ if (sOverrides.onSafelyStartInternalCallback != null
+ && sOverrides.onSafelyStartInternalCallback.apply(user)) {
+ return;
+ }
+ super.safelyStartActivityInternal(cti, user, options);
}
@Override
@@ -135,11 +139,29 @@
}
@Override
+ protected UserHandle getPersonalProfileUserHandle() {
+ return super.getPersonalProfileUserHandle();
+ }
+
+ @Override
protected UserHandle getWorkProfileUserHandle() {
return sOverrides.workProfileUserHandle;
}
@Override
+ protected UserHandle getCloneProfileUserHandle() {
+ return sOverrides.cloneProfileUserHandle;
+ }
+
+ @Override
+ protected UserHandle getTabOwnerUserHandleForLaunch() {
+ if (sOverrides.tabOwnerUserHandleForLaunch == null) {
+ return super.getTabOwnerUserHandleForLaunch();
+ }
+ return sOverrides.tabOwnerUserHandleForLaunch;
+ }
+
+ @Override
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
super.startActivityAsUser(intent, options, user);
}
@@ -153,24 +175,29 @@
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
+ public Function<UserHandle, Boolean> onSafelyStartInternalCallback;
public ResolverListController resolverListController;
public ResolverListController workResolverListController;
public Boolean isVoiceInteraction;
public UserHandle workProfileUserHandle;
+ public UserHandle cloneProfileUserHandle;
+ public UserHandle tabOwnerUserHandleForLaunch;
public Integer myUserId;
public boolean hasCrossProfileIntents;
public boolean isQuietModeEnabled;
public QuietModeManager mQuietModeManager;
- public MyUserIdProvider mMyUserIdProvider;
public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
public void reset() {
onSafelyStartCallback = null;
+ onSafelyStartInternalCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
resolverListController = mock(ResolverListController.class);
workResolverListController = mock(ResolverListController.class);
workProfileUserHandle = null;
+ cloneProfileUserHandle = null;
+ tabOwnerUserHandleForLaunch = null;
myUserId = null;
hasCrossProfileIntents = true;
isQuietModeEnabled = false;
@@ -197,13 +224,6 @@
}
};
- mMyUserIdProvider = new MyUserIdProvider() {
- @Override
- public int getMyUserId() {
- return myUserId != null ? myUserId : UserHandle.myUserId();
- }
- };
-
mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
.thenAnswer(invocation -> hasCrossProfileIntents);
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
new file mode 100644
index 0000000..9b9a84b
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app.procstats;
+
+import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import java.util.concurrent.TimeUnit;
+
+/** Provides test cases for ProcessStats. */
+public class ProcessStatsTest extends TestCase {
+
+ private static final String APP_1_PACKAGE_NAME = "com.android.testapp";
+ private static final int APP_1_UID = 5001;
+ private static final long APP_1_VERSION = 10;
+ private static final String APP_1_PROCESS_NAME = "com.android.testapp.p";
+ private static final String APP_1_SERVICE_NAME = "com.android.testapp.service";
+
+ private static final String APP_2_PACKAGE_NAME = "com.android.testapp2";
+ private static final int APP_2_UID = 5002;
+ private static final long APP_2_VERSION = 30;
+ private static final String APP_2_PROCESS_NAME = "com.android.testapp2.p";
+
+ private static final long NOW_MS = 123000;
+ private static final int DURATION_SECS = 6;
+
+ @Mock StatsEventOutput mStatsEventOutput;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ }
+
+ @SmallTest
+ public void testDumpProcessState() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processStats.getProcessStateLocked(
+ APP_2_PACKAGE_NAME, APP_2_UID, APP_2_VERSION, APP_2_PROCESS_NAME);
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testNonZeroProcessStateDuration() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ ProcessState processState =
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processState.setCombinedState(STATE_TOP, NOW_MS);
+ processState.commitStateTime(NOW_MS + TimeUnit.SECONDS.toMillis(DURATION_SECS));
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(DURATION_SECS),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testDumpProcessAssociation() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ AssociationState associationState =
+ processStats.getAssociationStateLocked(
+ APP_1_PACKAGE_NAME,
+ APP_1_UID,
+ APP_1_VERSION,
+ APP_1_PROCESS_NAME,
+ APP_1_SERVICE_NAME);
+ AssociationState.SourceState sourceState =
+ associationState.startSource(APP_2_UID, APP_2_PROCESS_NAME, APP_2_PACKAGE_NAME);
+ sourceState.stop();
+ processStats.dumpProcessAssociation(
+ FrameworkStatsLog.PROCESS_ASSOCIATION, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_ASSOCIATION),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ eq(APP_1_UID),
+ eq(APP_1_SERVICE_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(APP_1_PROCESS_NAME));
+ }
+}
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index e5000a4..b2914d8 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -110,8 +110,9 @@
private void sendNotification(int id, CharSequence text) {
// Fill in arbitrary content
- Intent intent = new Intent(Intent.ACTION_VIEW);
- PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ Intent intent = new Intent(Intent.ACTION_VIEW).setPackage(mContext.getPackageName());
+ PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent,
+ PendingIntent.FLAG_MUTABLE);
CharSequence title = text + " " + id;
CharSequence subtitle = String.valueOf(System.currentTimeMillis());
// Create "typical" notification with random icon
diff --git a/core/tests/screenshothelpertests/Android.bp b/core/tests/screenshothelpertests/Android.bp
index 37af99c..3c71e6e 100644
--- a/core/tests/screenshothelpertests/Android.bp
+++ b/core/tests/screenshothelpertests/Android.bp
@@ -13,7 +13,7 @@
srcs: [
"src/**/*.java",
],
-
+
static_libs: [
"frameworks-base-testutils",
"androidx.test.runner",
@@ -21,6 +21,7 @@
"androidx.test.ext.junit",
"mockito-target-minus-junit4",
"platform-test-annotations",
+ "testng",
],
libs: [
diff --git a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
index 2719431..5c9894e 100644
--- a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
+++ b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java
@@ -17,6 +17,7 @@
package com.android.internal.util;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -31,9 +32,11 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
import android.graphics.Insets;
import android.graphics.Rect;
-import android.os.Bundle;
+import android.hardware.HardwareBuffer;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
@@ -79,30 +82,48 @@
@Test
public void testFullscreenScreenshot() {
- mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN,
+ mScreenshotHelper.takeScreenshot(
WindowManager.ScreenshotSource.SCREENSHOT_OTHER, mHandler, null);
}
@Test
+ public void testFullscreenScreenshotRequest() {
+ ScreenshotRequest request = new ScreenshotRequest.Builder(
+ TAKE_SCREENSHOT_FULLSCREEN, WindowManager.ScreenshotSource.SCREENSHOT_OTHER)
+ .build();
+ mScreenshotHelper.takeScreenshot(request, mHandler, null);
+ }
+
+ @Test
public void testProvidedImageScreenshot() {
- mScreenshotHelper.provideScreenshot(
- new Bundle(), new Rect(), Insets.of(0, 0, 0, 0), 1, 1, new ComponentName("", ""),
- WindowManager.ScreenshotSource.SCREENSHOT_OTHER, mHandler, null);
+ HardwareBuffer buffer = HardwareBuffer.create(
+ 10, 10, HardwareBuffer.RGBA_8888, 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+ Bitmap bitmap = Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
+ ScreenshotRequest request = new ScreenshotRequest.Builder(
+ TAKE_SCREENSHOT_PROVIDED_IMAGE, WindowManager.ScreenshotSource.SCREENSHOT_OTHER)
+ .setTopComponent(new ComponentName("", ""))
+ .setTaskId(1)
+ .setUserId(1)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(new Rect())
+ .setInsets(Insets.NONE)
+ .build();
+ mScreenshotHelper.takeScreenshot(request, mHandler, null);
}
@Test
public void testScreenshotTimesOut() {
long timeoutMs = 10;
+ ScreenshotRequest request = new ScreenshotRequest.Builder(
+ TAKE_SCREENSHOT_FULLSCREEN, WindowManager.ScreenshotSource.SCREENSHOT_OTHER)
+ .build();
CountDownLatch lock = new CountDownLatch(1);
- mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN,
- WindowManager.ScreenshotSource.SCREENSHOT_OTHER,
- mHandler,
- timeoutMs,
+ mScreenshotHelper.takeScreenshotInternal(request, mHandler,
uri -> {
assertNull(uri);
lock.countDown();
- });
+ }, timeoutMs);
try {
// Add tolerance for delay to prevent flakes.
diff --git a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java
new file mode 100644
index 0000000..30540a5
--- /dev/null
+++ b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotRequestTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.os.UserHandle.USER_NULL;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER;
+import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.ComponentName;
+import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public final class ScreenshotRequestTest {
+ private final ComponentName mComponentName =
+ new ComponentName("android.test", "android.test.Component");
+
+ @Test
+ public void testSimpleScreenshot() {
+ ScreenshotRequest in =
+ new ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_OTHER).build();
+
+ Parcel parcel = Parcel.obtain();
+ in.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ ScreenshotRequest out = ScreenshotRequest.CREATOR.createFromParcel(parcel);
+
+ assertEquals(TAKE_SCREENSHOT_FULLSCREEN, out.getType());
+ assertEquals(SCREENSHOT_OTHER, out.getSource());
+ assertNull("Top component was expected to be null", out.getTopComponent());
+ assertEquals(INVALID_TASK_ID, out.getTaskId());
+ assertEquals(USER_NULL, out.getUserId());
+ assertNull("Bitmap was expected to be null", out.getBitmap());
+ assertNull("Bounds were expected to be null", out.getBoundsInScreen());
+ assertEquals(Insets.NONE, out.getInsets());
+ }
+
+ @Test
+ public void testProvidedScreenshot() {
+ Bitmap bitmap = makeHardwareBitmap(50, 50);
+ ScreenshotRequest in =
+ new ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(mComponentName)
+ .setTaskId(2)
+ .setUserId(3)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(new Rect(10, 10, 60, 60))
+ .setInsets(Insets.of(2, 3, 4, 5))
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ in.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ ScreenshotRequest out = ScreenshotRequest.CREATOR.createFromParcel(parcel);
+
+ assertEquals(TAKE_SCREENSHOT_PROVIDED_IMAGE, out.getType());
+ assertEquals(SCREENSHOT_OTHER, out.getSource());
+ assertEquals(mComponentName, out.getTopComponent());
+ assertEquals(2, out.getTaskId());
+ assertEquals(3, out.getUserId());
+ assertTrue("Bitmaps should be equal", out.getBitmap().sameAs(bitmap));
+ assertEquals(new Rect(10, 10, 60, 60), out.getBoundsInScreen());
+ assertEquals(Insets.of(2, 3, 4, 5), out.getInsets());
+ }
+
+ @Test
+ public void testProvidedScreenshot_nullBitmap() {
+ ScreenshotRequest.Builder inBuilder =
+ new ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(mComponentName)
+ .setTaskId(2)
+ .setUserId(3)
+ .setBoundsOnScreen(new Rect(10, 10, 60, 60))
+ .setInsets(Insets.of(2, 3, 4, 5));
+
+ assertThrows(IllegalStateException.class, inBuilder::build);
+ }
+
+ @Test
+ public void testFullScreenshot_withBitmap() {
+ // A bitmap added to a FULLSCREEN request will be ignored, but it's technically valid
+ Bitmap bitmap = makeHardwareBitmap(50, 50);
+ ScreenshotRequest in =
+ new ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_OTHER)
+ .setBitmap(bitmap)
+ .build();
+
+ Parcel parcel = Parcel.obtain();
+ in.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ ScreenshotRequest out = ScreenshotRequest.CREATOR.createFromParcel(parcel);
+
+ assertEquals(TAKE_SCREENSHOT_FULLSCREEN, out.getType());
+ assertEquals(SCREENSHOT_OTHER, out.getSource());
+ assertNull(out.getTopComponent());
+ assertEquals(INVALID_TASK_ID, out.getTaskId());
+ assertEquals(USER_NULL, out.getUserId());
+ assertTrue("Bitmaps should be equal", out.getBitmap().sameAs(bitmap));
+ assertNull("Bounds expected to be null", out.getBoundsInScreen());
+ assertEquals(Insets.NONE, out.getInsets());
+ }
+
+ private Bitmap makeHardwareBitmap(int width, int height) {
+ HardwareBuffer buffer = HardwareBuffer.create(
+ width, height, HardwareBuffer.RGBA_8888, 1, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
+ return Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
+ }
+}
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index bc3af1d..8b7265e 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -2599,6 +2599,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "273212558": {
+ "message": " info=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN",
+ "at": "com\/android\/server\/wm\/TransitionController.java"
+ },
"274773837": {
"message": "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL transit=%s Callers=%s",
"level": "VERBOSE",
@@ -3937,6 +3943,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1621562070": {
+ "message": " startWCT=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN",
+ "at": "com\/android\/server\/wm\/TransitionController.java"
+ },
"1628345525": {
"message": "Now opening app %s",
"level": "VERBOSE",
@@ -4345,6 +4357,12 @@
"group": "WM_DEBUG_ANIM",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "2021079047": {
+ "message": "%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_WINDOW_TRANSITIONS_MIN",
+ "at": "com\/android\/server\/wm\/TransitionController.java"
+ },
"2022422429": {
"message": "createAnimationAdapter(): container=%s",
"level": "DEBUG",
@@ -4551,6 +4569,9 @@
"WM_DEBUG_WINDOW_TRANSITIONS": {
"tag": "WindowManager"
},
+ "WM_DEBUG_WINDOW_TRANSITIONS_MIN": {
+ "tag": "WindowManager"
+ },
"WM_ERROR": {
"tag": "WindowManager"
},
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index af3f276..6b5238b 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -16,6 +16,8 @@
package android.graphics;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import java.io.OutputStream;
/**
@@ -63,7 +65,70 @@
private int mHeight;
/**
- * Construct an YuvImage.
+ * The color space of the image, defaults to SRGB
+ */
+ @NonNull private ColorSpace mColorSpace;
+
+ /**
+ * Array listing all supported ImageFormat that are supported by this class
+ */
+ private final static String[] sSupportedFormats =
+ {"NV21", "YUY2", "YCBCR_P010", "YUV_420_888"};
+
+ private static String printSupportedFormats() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < sSupportedFormats.length; ++i) {
+ sb.append(sSupportedFormats[i]);
+ if (i != sSupportedFormats.length - 1) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Array listing all supported HDR ColorSpaces that are supported by JPEG/R encoding
+ */
+ private final static ColorSpace.Named[] sSupportedJpegRHdrColorSpaces = {
+ ColorSpace.Named.BT2020_HLG,
+ ColorSpace.Named.BT2020_PQ
+ };
+
+ /**
+ * Array listing all supported SDR ColorSpaces that are supported by JPEG/R encoding
+ */
+ private final static ColorSpace.Named[] sSupportedJpegRSdrColorSpaces = {
+ ColorSpace.Named.SRGB,
+ ColorSpace.Named.DISPLAY_P3
+ };
+
+ private static String printSupportedJpegRColorSpaces(boolean isHdr) {
+ ColorSpace.Named[] colorSpaces = isHdr ? sSupportedJpegRHdrColorSpaces :
+ sSupportedJpegRSdrColorSpaces;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < colorSpaces.length; ++i) {
+ sb.append(ColorSpace.get(colorSpaces[i]).getName());
+ if (i != colorSpaces.length - 1) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+
+ private static boolean isSupportedJpegRColorSpace(boolean isHdr, int colorSpace) {
+ ColorSpace.Named[] colorSpaces = isHdr ? sSupportedJpegRHdrColorSpaces :
+ sSupportedJpegRSdrColorSpaces;
+ for (ColorSpace.Named cs : colorSpaces) {
+ if (cs.ordinal() == colorSpace) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Construct an YuvImage. Use SRGB for as default {@link ColorSpace}.
*
* @param yuv The YUV data. In the case of more than one image plane, all the planes must be
* concatenated into a single byte array.
@@ -77,11 +142,33 @@
* null.
*/
public YuvImage(byte[] yuv, int format, int width, int height, int[] strides) {
+ this(yuv, format, width, height, strides, ColorSpace.get(ColorSpace.Named.SRGB));
+ }
+
+ /**
+ * Construct an YuvImage.
+ *
+ * @param yuv The YUV data. In the case of more than one image plane, all the planes
+ * must be concatenated into a single byte array.
+ * @param format The YUV data format as defined in {@link ImageFormat}.
+ * @param width The width of the YuvImage.
+ * @param height The height of the YuvImage.
+ * @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the
+ * stride of each image must be provided. If strides is null, the method
+ * assumes no padding and derives the row bytes by format and width itself.
+ * @param colorSpace The YUV image color space as defined in {@link ColorSpace}.
+ * If the parameter is null, SRGB will be set as the default value.
+ * @throws IllegalArgumentException if format is not support; width or height <= 0; or yuv is
+ * null.
+ */
+ public YuvImage(@NonNull byte[] yuv, int format, int width, int height,
+ @Nullable int[] strides, @NonNull ColorSpace colorSpace) {
if (format != ImageFormat.NV21 &&
- format != ImageFormat.YUY2) {
+ format != ImageFormat.YUY2 &&
+ format != ImageFormat.YCBCR_P010 &&
+ format != ImageFormat.YUV_420_888) {
throw new IllegalArgumentException(
- "only support ImageFormat.NV21 " +
- "and ImageFormat.YUY2 for now");
+ "only supports the following ImageFormat:" + printSupportedFormats());
}
if (width <= 0 || height <= 0) {
@@ -93,6 +180,10 @@
throw new IllegalArgumentException("yuv cannot be null");
}
+ if (colorSpace == null) {
+ throw new IllegalArgumentException("ColorSpace cannot be null");
+ }
+
if (strides == null) {
mStrides = calculateStrides(width, format);
} else {
@@ -103,12 +194,13 @@
mFormat = format;
mWidth = width;
mHeight = height;
+ mColorSpace = colorSpace;
}
/**
* Compress a rectangle region in the YuvImage to a jpeg.
- * Only ImageFormat.NV21 and ImageFormat.YUY2
- * are supported for now.
+ * For image format, only ImageFormat.NV21 and ImageFormat.YUY2 are supported.
+ * For color space, only SRGB is supported.
*
* @param rectangle The rectangle region to be compressed. The medthod checks if rectangle is
* inside the image. Also, the method modifies rectangle if the chroma pixels
@@ -117,10 +209,18 @@
* small size, 100 meaning compress for max quality.
* @param stream OutputStream to write the compressed data.
* @return True if the compression is successful.
- * @throws IllegalArgumentException if rectangle is invalid; quality is not within [0,
- * 100]; or stream is null.
+ * @throws IllegalArgumentException if rectangle is invalid; color space or image format
+ * is not supported; quality is not within [0, 100]; or stream is null.
*/
public boolean compressToJpeg(Rect rectangle, int quality, OutputStream stream) {
+ if (mFormat != ImageFormat.NV21 && mFormat != ImageFormat.YUY2) {
+ throw new IllegalArgumentException(
+ "Only ImageFormat.NV21 and ImageFormat.YUY2 are supported.");
+ }
+ if (mColorSpace.getId() != ColorSpace.Named.SRGB.ordinal()) {
+ throw new IllegalArgumentException("Only SRGB color space is supported.");
+ }
+
Rect wholeImage = new Rect(0, 0, mWidth, mHeight);
if (!wholeImage.contains(rectangle)) {
throw new IllegalArgumentException(
@@ -143,6 +243,70 @@
new byte[WORKING_COMPRESS_STORAGE]);
}
+ /**
+ * Compress the HDR image into JPEG/R format.
+ *
+ * Sample usage:
+ * hdr_image.compressToJpegR(sdr_image, 90, stream);
+ *
+ * For the SDR image, only YUV_420_888 image format is supported, and the following
+ * color spaces are supported:
+ * ColorSpace.Named.SRGB,
+ * ColorSpace.Named.DISPLAY_P3
+ *
+ * For the HDR image, only YCBCR_P010 image format is supported, and the following
+ * color spaces are supported:
+ * ColorSpace.Named.BT2020_HLG,
+ * ColorSpace.Named.BT2020_PQ
+ *
+ * @param sdr The SDR image, only ImageFormat.YUV_420_888 is supported.
+ * @param quality Hint to the compressor, 0-100. 0 meaning compress for
+ * small size, 100 meaning compress for max quality.
+ * @param stream OutputStream to write the compressed data.
+ * @return True if the compression is successful.
+ * @throws IllegalArgumentException if input images are invalid; quality is not within [0,
+ * 100]; or stream is null.
+ */
+ public boolean compressToJpegR(@NonNull YuvImage sdr, int quality,
+ @NonNull OutputStream stream) {
+ if (sdr == null) {
+ throw new IllegalArgumentException("SDR input cannot be null");
+ }
+
+ if (mData.length == 0 || sdr.getYuvData().length == 0) {
+ throw new IllegalArgumentException("Input images cannot be empty");
+ }
+
+ if (mFormat != ImageFormat.YCBCR_P010 || sdr.getYuvFormat() != ImageFormat.YUV_420_888) {
+ throw new IllegalArgumentException(
+ "only support ImageFormat.YCBCR_P010 and ImageFormat.YUV_420_888");
+ }
+
+ if (sdr.getWidth() != mWidth || sdr.getHeight() != mHeight) {
+ throw new IllegalArgumentException("HDR and SDR resolution mismatch");
+ }
+
+ if (quality < 0 || quality > 100) {
+ throw new IllegalArgumentException("quality must be 0..100");
+ }
+
+ if (stream == null) {
+ throw new IllegalArgumentException("stream cannot be null");
+ }
+
+ if (!isSupportedJpegRColorSpace(true, mColorSpace.getId()) ||
+ !isSupportedJpegRColorSpace(false, sdr.getColorSpace().getId())) {
+ throw new IllegalArgumentException("Not supported color space. "
+ + "SDR only supports: " + printSupportedJpegRColorSpaces(false)
+ + "HDR only supports: " + printSupportedJpegRColorSpaces(true));
+ }
+
+ return nativeCompressToJpegR(mData, mColorSpace.getDataSpace(),
+ sdr.getYuvData(), sdr.getColorSpace().getDataSpace(),
+ mWidth, mHeight, quality, stream,
+ new byte[WORKING_COMPRESS_STORAGE]);
+ }
+
/**
* @return the YUV data.
@@ -179,6 +343,12 @@
return mHeight;
}
+
+ /**
+ * @return the color space of the image.
+ */
+ public @NonNull ColorSpace getColorSpace() { return mColorSpace; }
+
int[] calculateOffsets(int left, int top) {
int[] offsets = null;
if (mFormat == ImageFormat.NV21) {
@@ -198,17 +368,23 @@
private int[] calculateStrides(int width, int format) {
int[] strides = null;
- if (format == ImageFormat.NV21) {
+ switch (format) {
+ case ImageFormat.NV21:
strides = new int[] {width, width};
return strides;
- }
-
- if (format == ImageFormat.YUY2) {
+ case ImageFormat.YCBCR_P010:
+ strides = new int[] {width * 2, width * 2};
+ return strides;
+ case ImageFormat.YUV_420_888:
+ strides = new int[] {width, (width + 1) / 2, (width + 1) / 2};
+ return strides;
+ case ImageFormat.YUY2:
strides = new int[] {width * 2};
return strides;
+ default:
+ throw new IllegalArgumentException(
+ "only supports the following ImageFormat:" + printSupportedFormats());
}
-
- return strides;
}
private void adjustRectangle(Rect rect) {
@@ -237,4 +413,8 @@
private static native boolean nativeCompressToJpeg(byte[] oriYuv,
int format, int width, int height, int[] offsets, int[] strides,
int quality, OutputStream stream, byte[] tempStorage);
+
+ private static native boolean nativeCompressToJpegR(byte[] hdr, int hdrColorSpaceId,
+ byte[] sdr, int sdrColorSpaceId, int width, int height, int quality,
+ OutputStream stream, byte[] tempStorage);
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 1a878df..4d0a058 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -25,7 +25,6 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.ValueAnimator;
-import android.annotation.ColorInt;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -993,9 +992,9 @@
RippleShader shader = new RippleShader();
// Grab the color for the current state and cut the alpha channel in
// half so that the ripple and background together yield full alpha.
- final int color = clampAlpha(mMaskColorFilter == null
+ final int color = mMaskColorFilter == null
? mState.mColor.getColorForState(getState(), Color.BLACK)
- : mMaskColorFilter.getColor());
+ : mMaskColorFilter.getColor();
final int effectColor = mState.mEffectColor.getColorForState(getState(), Color.MAGENTA);
final float noisePhase = AnimationUtils.currentAnimationTimeMillis();
shader.setColor(color, effectColor);
@@ -1018,13 +1017,6 @@
return properties;
}
- private int clampAlpha(@ColorInt int color) {
- if (Color.alpha(color) < 128) {
- return (color & 0x00FFFFFF) | 0x80000000;
- }
- return color;
- }
-
@Override
public void invalidateSelf() {
invalidateSelf(true);
@@ -1239,7 +1231,7 @@
// Grab the color for the current state and cut the alpha channel in
// half so that the ripple and background together yield full alpha.
- final int color = clampAlpha(mState.mColor.getColorForState(getState(), Color.BLACK));
+ final int color = mState.mColor.getColorForState(getState(), Color.BLACK);
final Paint p = mRipplePaint;
if (mMaskColorFilter != null) {
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 528c51d2..57a8977 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -19,7 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="pip_phone_close" msgid="5783752637260411309">"Жабуу"</string>
<string name="pip_phone_expand" msgid="2579292903468287504">"Жайып көрсөтүү"</string>
- <string name="pip_phone_settings" msgid="5468987116750491918">"Жөндөөлөр"</string>
+ <string name="pip_phone_settings" msgid="5468987116750491918">"Параметрлер"</string>
<string name="pip_phone_enter_split" msgid="7042877263880641911">"Экранды бөлүү режимине өтүү"</string>
<string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
<string name="pip_menu_accessibility_title" msgid="8129016817688656249">"Сүрөт ичиндеги сүрөт менюсу"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
index 5d38494..38f1e28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
@@ -31,11 +31,12 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.RemoteException;
+import android.util.FloatProperty;
+import android.util.TypedValue;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.window.BackEvent;
@@ -43,9 +44,10 @@
import android.window.BackProgressAnimator;
import android.window.IOnBackInvokedCallback;
+import com.android.internal.dynamicanimation.animation.SpringAnimation;
+import com.android.internal.dynamicanimation.animation.SpringForce;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.protolog.common.ProtoLog;
-import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.annotations.ShellMainThread;
/** Class that defines cross-activity animation. */
@@ -56,24 +58,40 @@
*/
private static final float MIN_WINDOW_SCALE = 0.9f;
- /**
- * Minimum alpha of the closing/entering window.
- */
- private static final float CLOSING_MIN_WINDOW_ALPHA = 0.5f;
-
- /**
- * Progress value to fly out closing window and fly in entering window.
- */
- private static final float SWITCH_ENTERING_WINDOW_PROGRESS = 0.5f;
-
- /** Max window translation in the Y axis. */
- private static final int WINDOW_MAX_DELTA_Y = 160;
-
- /** Duration of fade in/out entering window. */
- private static final int FADE_IN_DURATION = 100;
/** Duration of post animation after gesture committed. */
private static final int POST_ANIMATION_DURATION = 350;
- private static final Interpolator INTERPOLATOR = Interpolators.EMPHASIZED;
+ private static final Interpolator INTERPOLATOR = new DecelerateInterpolator();
+ private static final FloatProperty<CrossActivityAnimation> ENTER_PROGRESS_PROP =
+ new FloatProperty<>("enter-alpha") {
+ @Override
+ public void setValue(CrossActivityAnimation anim, float value) {
+ anim.setEnteringProgress(value);
+ }
+
+ @Override
+ public Float get(CrossActivityAnimation object) {
+ return object.getEnteringProgress();
+ }
+ };
+ private static final FloatProperty<CrossActivityAnimation> LEAVE_PROGRESS_PROP =
+ new FloatProperty<>("leave-alpha") {
+ @Override
+ public void setValue(CrossActivityAnimation anim, float value) {
+ anim.setLeavingProgress(value);
+ }
+
+ @Override
+ public Float get(CrossActivityAnimation object) {
+ return object.getLeavingProgress();
+ }
+ };
+ private static final float MIN_WINDOW_ALPHA = 0.01f;
+ private static final float WINDOW_X_SHIFT_DP = 96;
+ private static final int SCALE_FACTOR = 100;
+ // TODO(b/264710590): Use the progress commit threshold from ViewConfiguration once it exists.
+ private static final float PROGRESS_COMMIT_THRESHOLD = 0.1f;
+ private static final float TARGET_COMMIT_PROGRESS = 0.5f;
+ private static final float ENTER_ALPHA_THRESHOLD = 0.22f;
private final Rect mStartTaskRect = new Rect();
private final float mCornerRadius;
@@ -84,12 +102,13 @@
// The entering window properties.
private final Rect mEnteringStartRect = new Rect();
private final RectF mEnteringRect = new RectF();
+ private final SpringAnimation mEnteringProgressSpring;
+ private final SpringAnimation mLeavingProgressSpring;
+ // Max window x-shift in pixels.
+ private final float mWindowXShift;
- private float mCurrentAlpha = 1.0f;
-
- private float mEnteringMargin = 0;
- private ValueAnimator mEnteringAnimator;
- private boolean mEnteringWindowShow = false;
+ private float mEnteringProgress = 0f;
+ private float mLeavingProgress = 0f;
private final PointF mInitialTouchPos = new PointF();
@@ -115,16 +134,44 @@
mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
mBackground = background;
+ mEnteringProgressSpring = new SpringAnimation(this, ENTER_PROGRESS_PROP);
+ mEnteringProgressSpring.setSpring(new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
+ mLeavingProgressSpring = new SpringAnimation(this, LEAVE_PROGRESS_PROP);
+ mLeavingProgressSpring.setSpring(new SpringForce()
+ .setStiffness(SpringForce.STIFFNESS_MEDIUM)
+ .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY));
+ mWindowXShift = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, WINDOW_X_SHIFT_DP,
+ context.getResources().getDisplayMetrics());
}
+ /**
+ * Returns 1 if x >= edge1, 0 if x <= edge0, and a smoothed value between the two.
+ * From https://en.wikipedia.org/wiki/Smoothstep
+ */
+ private static float smoothstep(float edge0, float edge1, float x) {
+ if (x < edge0) return 0;
+ if (x >= edge1) return 1;
+
+ x = (x - edge0) / (edge1 - edge0);
+ return x * x * (3 - 2 * x);
+ }
+
+ /**
+ * Linearly map x from range (a1, a2) to range (b1, b2).
+ */
+ private static float mapLinear(float x, float a1, float a2, float b1, float b2) {
+ return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
+ }
+
+ /**
+ * Linearly map a normalized value from (0, 1) to (min, max).
+ */
private static float mapRange(float value, float min, float max) {
return min + (value * (max - min));
}
- private float getInterpolatedProgress(float backProgress) {
- return INTERPOLATOR.getInterpolation(backProgress);
- }
-
private void startBackAnimation() {
if (mEnteringTarget == null || mClosingTarget == null) {
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Entering target or closing target is null.");
@@ -169,9 +216,6 @@
mBackInProgress = false;
mTransformMatrix.reset();
mInitialTouchPos.set(0, 0);
- mEnteringWindowShow = false;
- mEnteringMargin = 0;
- mEnteringAnimator = null;
if (mFinishCallback != null) {
try {
@@ -181,6 +225,10 @@
}
mFinishCallback = null;
}
+ mEnteringProgressSpring.animateToFinalPosition(0);
+ mEnteringProgressSpring.skipToEnd();
+ mLeavingProgressSpring.animateToFinalPosition(0);
+ mLeavingProgressSpring.skipToEnd();
}
private void onGestureProgress(@NonNull BackEvent backEvent) {
@@ -190,84 +238,12 @@
}
mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());
- if (mEnteringTarget == null || mClosingTarget == null) {
- return;
- }
-
- final float progress = getInterpolatedProgress(backEvent.getProgress());
- final float touchY = mTouchPos.y;
-
- final int width = mStartTaskRect.width();
- final int height = mStartTaskRect.height();
-
- final float closingScale = mapRange(progress, 1, MIN_WINDOW_SCALE);
-
- final float closingWidth = closingScale * width;
- final float closingHeight = (float) height / width * closingWidth;
-
- // Move the window along the X axis.
- final float closingLeft = mStartTaskRect.left + (width - closingWidth) / 2;
-
- // Move the window along the Y axis.
- final float deltaYRatio = (touchY - mInitialTouchPos.y) / height;
- final float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * WINDOW_MAX_DELTA_Y;
- final float closingTop = (height - closingHeight) * 0.5f + deltaY;
- mClosingRect.set(
- closingLeft, closingTop, closingLeft + closingWidth, closingTop + closingHeight);
- mEnteringRect.set(mClosingRect);
-
- // Switch closing/entering targets while reach to the threshold progress.
- if (showEnteringWindow(progress > SWITCH_ENTERING_WINDOW_PROGRESS)) {
- return;
- }
-
- // Present windows and update the alpha.
- mCurrentAlpha = Math.max(mapRange(progress, 1.0f, 0), CLOSING_MIN_WINDOW_ALPHA);
- mClosingRect.offset(mEnteringMargin, 0);
- mEnteringRect.offset(mEnteringMargin - width, 0);
-
- applyTransform(
- mClosingTarget.leash, mClosingRect, mEnteringWindowShow ? 0.01f : mCurrentAlpha);
- applyTransform(
- mEnteringTarget.leash, mEnteringRect, mEnteringWindowShow ? mCurrentAlpha : 0.01f);
- mTransaction.apply();
- }
-
- private boolean showEnteringWindow(boolean show) {
- if (mEnteringAnimator == null) {
- mEnteringAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(FADE_IN_DURATION);
- mEnteringAnimator.setInterpolator(new AccelerateInterpolator());
- mEnteringAnimator.addUpdateListener(animation -> {
- float progress = animation.getAnimatedFraction();
- final int width = mStartTaskRect.width();
- mEnteringMargin = width * progress;
- // We don't animate to 0 or the surface would become invisible and lose focus.
- final float alpha = progress >= 0.5f ? 0.01f
- : mapRange(progress * 2, mCurrentAlpha, 0.01f);
- mClosingRect.offset(mEnteringMargin, 0);
- mEnteringRect.offset(mEnteringMargin - width, 0);
-
- applyTransform(mClosingTarget.leash, mClosingRect, alpha);
- applyTransform(mEnteringTarget.leash, mEnteringRect, mCurrentAlpha);
- mTransaction.apply();
- });
- }
-
- if (mEnteringAnimator.isRunning()) {
- return true;
- }
-
- if (mEnteringWindowShow == show) {
- return false;
- }
-
- mEnteringWindowShow = show;
- if (show) {
- mEnteringAnimator.start();
- } else {
- mEnteringAnimator.reverse();
- }
- return true;
+ float progress = backEvent.getProgress();
+ float springProgress = (progress > PROGRESS_COMMIT_THRESHOLD
+ ? mapLinear(progress, 0.1f, 1, TARGET_COMMIT_PROGRESS, 1)
+ : mapLinear(progress, 0, 1f, 0, TARGET_COMMIT_PROGRESS)) * SCALE_FACTOR;
+ mLeavingProgressSpring.animateToFinalPosition(springProgress);
+ mEnteringProgressSpring.animateToFinalPosition(springProgress);
}
private void onGestureCommitted() {
@@ -275,11 +251,9 @@
finishAnimation();
return;
}
-
- // End the fade in animation.
- if (mEnteringAnimator != null && mEnteringAnimator.isRunning()) {
- mEnteringAnimator.cancel();
- }
+ // End the fade animations
+ mLeavingProgressSpring.cancel();
+ mEnteringProgressSpring.cancel();
// We enter phase 2 of the animation, the starting coordinates for phase 2 are the current
// coordinate of the gesture driven phase.
@@ -309,12 +283,79 @@
float top = mapRange(progress, mEnteringStartRect.top, mStartTaskRect.top);
float width = mapRange(progress, mEnteringStartRect.width(), mStartTaskRect.width());
float height = mapRange(progress, mEnteringStartRect.height(), mStartTaskRect.height());
- float alpha = mapRange(progress, mCurrentAlpha, 1.0f);
+ float alpha = mapRange(progress, mEnteringProgress, 1.0f);
mEnteringRect.set(left, top, left + width, top + height);
applyTransform(mEnteringTarget.leash, mEnteringRect, alpha);
}
+ private float getEnteringProgress() {
+ return mEnteringProgress * SCALE_FACTOR;
+ }
+
+ private void setEnteringProgress(float value) {
+ mEnteringProgress = value / SCALE_FACTOR;
+ if (mEnteringTarget != null && mEnteringTarget.leash != null) {
+ transformWithProgress(
+ mEnteringProgress,
+ Math.max(
+ smoothstep(ENTER_ALPHA_THRESHOLD, 1, mEnteringProgress),
+ MIN_WINDOW_ALPHA), /* alpha */
+ mEnteringTarget.leash,
+ mEnteringRect,
+ -mWindowXShift,
+ 0
+ );
+ }
+ }
+
+ private float getLeavingProgress() {
+ return mLeavingProgress * SCALE_FACTOR;
+ }
+
+ private void setLeavingProgress(float value) {
+ mLeavingProgress = value / SCALE_FACTOR;
+ if (mClosingTarget != null && mClosingTarget.leash != null) {
+ transformWithProgress(
+ mLeavingProgress,
+ Math.max(
+ 1 - smoothstep(0, ENTER_ALPHA_THRESHOLD, mLeavingProgress),
+ MIN_WINDOW_ALPHA),
+ mClosingTarget.leash,
+ mClosingRect,
+ 0,
+ mWindowXShift
+ );
+ }
+ }
+
+ private void transformWithProgress(float progress, float alpha, SurfaceControl surface,
+ RectF targetRect, float deltaXMin, float deltaXMax) {
+ final float touchY = mTouchPos.y;
+
+ final int width = mStartTaskRect.width();
+ final int height = mStartTaskRect.height();
+
+ final float interpolatedProgress = INTERPOLATOR.getInterpolation(progress);
+ final float closingScale = MIN_WINDOW_SCALE
+ + (1 - interpolatedProgress) * (1 - MIN_WINDOW_SCALE);
+ final float closingWidth = closingScale * width;
+ final float closingHeight = (float) height / width * closingWidth;
+
+ // Move the window along the X axis.
+ float closingLeft = mStartTaskRect.left + (width - closingWidth) / 2;
+ closingLeft += mapRange(interpolatedProgress, deltaXMin, deltaXMax);
+
+ // Move the window along the Y axis.
+ final float deltaYRatio = (touchY - mInitialTouchPos.y) / height;
+ final float closingTop = (height - closingHeight) * 0.5f;
+ targetRect.set(
+ closingLeft, closingTop, closingLeft + closingWidth, closingTop + closingHeight);
+
+ applyTransform(surface, targetRect, Math.max(alpha, MIN_WINDOW_ALPHA));
+ mTransaction.apply();
+ }
+
private final class Callback extends IOnBackInvokedCallback.Default {
@Override
public void onBackStarted(BackMotionEvent backEvent) {
@@ -330,10 +371,12 @@
@Override
public void onBackCancelled() {
// End the fade in animation.
- if (mEnteringAnimator != null && mEnteringAnimator.isRunning()) {
- mEnteringAnimator.cancel();
- }
mProgressAnimator.onBackCancelled(CrossActivityAnimation.this::finishAnimation);
+ mEnteringProgressSpring.cancel();
+ mLeavingProgressSpring.cancel();
+ // TODO (b259608500): Let BackProgressAnimator could play cancel animation.
+ mProgressAnimator.reset();
+ finishAnimation();
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 9edfffc..d0aef20 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -384,7 +384,7 @@
@Nullable ImeTracker.Token statsToken) {
final InsetsSource imeSource = mInsetsState.getSource(InsetsState.ITYPE_IME);
if (imeSource == null || mImeSourceControl == null) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
final Rect newFrame = imeSource.getFrame();
@@ -407,8 +407,7 @@
}
if ((!forceRestart && (mAnimationDirection == DIRECTION_SHOW && show))
|| (mAnimationDirection == DIRECTION_HIDE && !show)) {
- ImeTracker.forLogging().onCancelled(
- statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
boolean seek = false;
@@ -452,7 +451,7 @@
mTransactionPool.release(t);
});
mAnimation.setInterpolator(INTERPOLATOR);
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
mAnimation.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled = false;
@Nullable
@@ -475,7 +474,7 @@
: 1.f;
t.setAlpha(mImeSourceControl.getLeash(), alpha);
if (mAnimationDirection == DIRECTION_SHOW) {
- ImeTracker.forLogging().onProgress(mStatsToken,
+ ImeTracker.get().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
t.show(mImeSourceControl.getLeash());
}
@@ -512,15 +511,15 @@
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
- ImeTracker.forLogging().onProgress(mStatsToken,
+ ImeTracker.get().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
t.hide(mImeSourceControl.getLeash());
removeImeSurface();
- ImeTracker.forLogging().onHidden(mStatsToken);
+ ImeTracker.get().onHidden(mStatsToken);
} else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
- ImeTracker.forLogging().onShown(mStatsToken);
+ ImeTracker.get().onShown(mStatsToken);
} else if (mCancelled) {
- ImeTracker.forLogging().onCancelled(mStatsToken,
+ ImeTracker.get().onCancelled(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
}
if (DEBUG_IME_VISIBILITY) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
index 9bdda14..8759301 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayInsetsController.java
@@ -162,12 +162,10 @@
@Nullable ImeTracker.Token statsToken) {
CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
if (listeners == null) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
return;
}
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
for (OnInsetsChangedListener listener : listeners) {
listener.showInsets(types, fromIme, statsToken);
}
@@ -177,12 +175,10 @@
@Nullable ImeTracker.Token statsToken) {
CopyOnWriteArrayList<OnInsetsChangedListener> listeners = mListeners.get(mDisplayId);
if (listeners == null) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
return;
}
- ImeTracker.forLogging().onProgress(
- statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROLLER);
for (OnInsetsChangedListener listener : listeners) {
listener.hideInsets(types, fromIme, statsToken);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 96efeeb..8484013 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -96,8 +96,7 @@
/**
* Different from {@link #equals(Object)}, this method compares the basic geometry properties
- * of two {@link DisplayLayout} objects including width, height, rotation, density, cutout and
- * insets.
+ * of two {@link DisplayLayout} objects including width, height, rotation, density, cutout.
* @return {@code true} if the given {@link DisplayLayout} is identical geometry wise.
*/
public boolean isSameGeometry(@NonNull DisplayLayout other) {
@@ -105,8 +104,7 @@
&& mHeight == other.mHeight
&& mRotation == other.mRotation
&& mDensityDpi == other.mDensityDpi
- && Objects.equals(mCutout, other.mCutout)
- && Objects.equals(mStableInsets, other.mStableInsets);
+ && Objects.equals(mCutout, other.mCutout);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index e83854e..525beb1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -616,7 +616,7 @@
return;
}
int oldMaxMovementBound = mPipBoundsState.getMovementBounds().bottom;
- onDisplayChanged(
+ onDisplayChangedUncheck(
mDisplayController.getDisplayLayout(mPipBoundsState.getDisplayId()),
false /* saveRestoreSnapFraction */);
int newMaxMovementBound = mPipBoundsState.getMovementBounds().bottom;
@@ -702,9 +702,12 @@
}
private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
- if (mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
- return;
+ if (!mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
+ onDisplayChangedUncheck(layout, saveRestoreSnapFraction);
}
+ }
+
+ private void onDisplayChangedUncheck(DisplayLayout layout, boolean saveRestoreSnapFraction) {
Runnable updateDisplayLayout = () -> {
final boolean fromRotation = Transitions.ENABLE_SHELL_TRANSITIONS
&& mPipBoundsState.getDisplayLayout().rotation() != layout.rotation();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 83bc7c0..850c561 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -337,8 +337,10 @@
mMotionHelper.synchronizePinnedStackBounds();
reloadResources();
- // Recreate the dismiss target for the new orientation.
- mPipDismissTargetHandler.createOrUpdateDismissTarget();
+ if (mPipTaskOrganizer.isInPip()) {
+ // Recreate the dismiss target for the new orientation.
+ mPipDismissTargetHandler.createOrUpdateDismissTarget();
+ }
}
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 618c446..36ce0a6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -445,7 +445,6 @@
backgroundColorForTransition = getTransitionBackgroundColorIfSet(info, change, a,
backgroundColorForTransition);
- boolean delayedEdgeExtension = false;
if (!isTask && a.hasExtension()) {
if (!Transitions.isOpeningType(change.getMode())) {
// Can screenshot now (before startTransaction is applied)
@@ -455,7 +454,6 @@
// may not be visible or ready yet.
postStartTransactionCallbacks
.add(t -> edgeExtendWindow(change, a, t, finishTransaction));
- delayedEdgeExtension = true;
}
}
@@ -464,19 +462,9 @@
: new Rect(change.getEndAbsBounds());
clipRect.offsetTo(0, 0);
- if (delayedEdgeExtension) {
- // If the edge extension needs to happen after the startTransition has been
- // applied, then we want to only start the animation after the edge extension
- // postStartTransaction callback has been run
- postStartTransactionCallbacks.add(t ->
- startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
- mTransactionPool, mMainExecutor, mAnimExecutor,
- change.getEndRelOffset(), cornerRadius, clipRect));
- } else {
- startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
- mTransactionPool, mMainExecutor, mAnimExecutor,
- change.getEndRelOffset(), cornerRadius, clipRect);
- }
+ buildSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
+ mTransactionPool, mMainExecutor, change.getEndRelOffset(), cornerRadius,
+ clipRect);
if (info.getAnimationOptions() != null) {
attachThumbnail(animations, onAnimFinish, change, info.getAnimationOptions(),
@@ -490,19 +478,25 @@
startTransaction, finishTransaction);
}
- // postStartTransactionCallbacks require that the start transaction is already
- // applied to run otherwise they may result in flickers and UI inconsistencies.
- boolean waitForStartTransactionApply = postStartTransactionCallbacks.size() > 0;
- startTransaction.apply(waitForStartTransactionApply);
-
- // Run tasks that require startTransaction to already be applied
- for (Consumer<SurfaceControl.Transaction> postStartTransactionCallback :
- postStartTransactionCallbacks) {
- final SurfaceControl.Transaction t = mTransactionPool.acquire();
- postStartTransactionCallback.accept(t);
- t.apply();
- mTransactionPool.release(t);
+ if (postStartTransactionCallbacks.size() > 0) {
+ // postStartTransactionCallbacks require that the start transaction is already
+ // applied to run otherwise they may result in flickers and UI inconsistencies.
+ startTransaction.apply(true /* sync */);
+ // startTransaction is empty now, so fill it with the edge-extension setup
+ for (Consumer<SurfaceControl.Transaction> postStartTransactionCallback :
+ postStartTransactionCallbacks) {
+ postStartTransactionCallback.accept(startTransaction);
+ }
}
+ startTransaction.apply();
+
+ // now start animations. they are started on another thread, so we have to post them
+ // *after* applying the startTransaction
+ mAnimExecutor.execute(() -> {
+ for (int i = 0; i < animations.size(); ++i) {
+ animations.get(i).start();
+ }
+ });
mRotator.cleanUp(finishTransaction);
TransitionMetrics.getInstance().reportAnimationStart(transition);
@@ -539,8 +533,8 @@
animations.removeAll(animGroupStore);
onAnimFinish.run();
};
- anim.startAnimation(animGroup, finishCallback, mTransitionAnimationScaleSetting,
- mMainExecutor, mAnimExecutor);
+ anim.buildAnimation(animGroup, finishCallback, mTransitionAnimationScaleSetting,
+ mMainExecutor);
for (int i = animGroup.size() - 1; i >= 0; i--) {
final Animator animator = animGroup.get(i);
animGroupStore.add(animator);
@@ -633,11 +627,12 @@
return a;
}
- static void startSurfaceAnimation(@NonNull ArrayList<Animator> animations,
+ /** Builds an animator for the surface and adds it to the `animations` list. */
+ static void buildSurfaceAnimation(@NonNull ArrayList<Animator> animations,
@NonNull Animation anim, @NonNull SurfaceControl leash,
@NonNull Runnable finishCallback, @NonNull TransactionPool pool,
- @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor,
- @Nullable Point position, float cornerRadius, @Nullable Rect clipRect) {
+ @NonNull ShellExecutor mainExecutor, @Nullable Point position, float cornerRadius,
+ @Nullable Rect clipRect) {
final SurfaceControl.Transaction transaction = pool.acquire();
final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
final Transformation transformation = new Transformation();
@@ -691,7 +686,6 @@
}
});
animations.add(va);
- animExecutor.execute(va::start);
}
private void attachThumbnail(@NonNull ArrayList<Animator> animations,
@@ -745,9 +739,8 @@
};
a.restrictDuration(MAX_ANIMATION_DURATION);
a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
- mMainExecutor, mAnimExecutor, change.getEndRelOffset(),
- cornerRadius, change.getEndAbsBounds());
+ buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
+ mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds());
}
private void attachThumbnailAnimation(@NonNull ArrayList<Animator> animations,
@@ -770,9 +763,8 @@
};
a.restrictDuration(MAX_ANIMATION_DURATION);
a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
- mMainExecutor, mAnimExecutor, change.getEndRelOffset(),
- cornerRadius, change.getEndAbsBounds());
+ buildSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
+ mMainExecutor, change.getEndRelOffset(), cornerRadius, change.getEndAbsBounds());
}
private static int getWallpaperTransitType(TransitionInfo info) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 665267f..e643170 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -21,7 +21,7 @@
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
import static android.view.WindowManagerPolicyConstants.SCREEN_FREEZE_LAYER_BASE;
-import static com.android.wm.shell.transition.DefaultTransitionHandler.startSurfaceAnimation;
+import static com.android.wm.shell.transition.DefaultTransitionHandler.buildSurfaceAnimation;
import static com.android.wm.shell.transition.Transitions.TAG;
import android.animation.Animator;
@@ -244,11 +244,11 @@
}
/**
- * Returns true if animating.
+ * Returns true if any animations were added to `animations`.
*/
- public boolean startAnimation(@NonNull ArrayList<Animator> animations,
+ boolean buildAnimation(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, float animationScale,
- @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+ @NonNull ShellExecutor mainExecutor) {
if (mScreenshotLayer == null) {
// Can't do animation.
return false;
@@ -311,13 +311,11 @@
mRotateAlphaAnimation.restrictDuration(MAX_ANIMATION_DURATION);
mRotateAlphaAnimation.scaleCurrentDuration(animationScale);
- startScreenshotAlphaAnimation(animations, finishCallback, mainExecutor,
- animExecutor);
- startDisplayRotation(animations, finishCallback, mainExecutor, animExecutor);
+ buildScreenshotAlphaAnimation(animations, finishCallback, mainExecutor);
+ startDisplayRotation(animations, finishCallback, mainExecutor);
} else {
- startDisplayRotation(animations, finishCallback, mainExecutor, animExecutor);
- startScreenshotRotationAnimation(animations, finishCallback, mainExecutor,
- animExecutor);
+ startDisplayRotation(animations, finishCallback, mainExecutor);
+ startScreenshotRotationAnimation(animations, finishCallback, mainExecutor);
//startColorAnimation(mTransaction, animationScale);
}
@@ -325,27 +323,24 @@
}
private void startDisplayRotation(@NonNull ArrayList<Animator> animations,
- @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
- @NonNull ShellExecutor animExecutor) {
- startSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback,
- mTransactionPool, mainExecutor, animExecutor, null /* position */,
- 0 /* cornerRadius */, null /* clipRect */);
+ @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) {
+ buildSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback,
+ mTransactionPool, mainExecutor, null /* position */, 0 /* cornerRadius */,
+ null /* clipRect */);
}
private void startScreenshotRotationAnimation(@NonNull ArrayList<Animator> animations,
- @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
- @NonNull ShellExecutor animExecutor) {
- startSurfaceAnimation(animations, mRotateExitAnimation, mAnimLeash, finishCallback,
- mTransactionPool, mainExecutor, animExecutor, null /* position */,
- 0 /* cornerRadius */, null /* clipRect */);
+ @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) {
+ buildSurfaceAnimation(animations, mRotateExitAnimation, mAnimLeash, finishCallback,
+ mTransactionPool, mainExecutor, null /* position */, 0 /* cornerRadius */,
+ null /* clipRect */);
}
- private void startScreenshotAlphaAnimation(@NonNull ArrayList<Animator> animations,
- @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
- @NonNull ShellExecutor animExecutor) {
- startSurfaceAnimation(animations, mRotateAlphaAnimation, mAnimLeash, finishCallback,
- mTransactionPool, mainExecutor, animExecutor, null /* position */,
- 0 /* cornerRadius */, null /* clipRect */);
+ private void buildScreenshotAlphaAnimation(@NonNull ArrayList<Animator> animations,
+ @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor) {
+ buildSurfaceAnimation(animations, mRotateAlphaAnimation, mAnimLeash, finishCallback,
+ mTransactionPool, mainExecutor, null /* position */, 0 /* cornerRadius */,
+ null /* clipRect */);
}
private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) {
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
index 06df9568..4721741 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
@@ -46,7 +46,7 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<!-- Allow the test to write directly to /sdcard/ -->
- <application android:requestLegacyExternalStorage="true">
+ <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<service android:name=".NotificationListener"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 8a694f7..7aa40e7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -70,6 +70,18 @@
@Presubmit
@Test
+ override fun pipAppWindowAlwaysVisible() {
+ // In gestural nav the pip will first move behind home and then above home. The visual
+ // appearance visible->invisible->visible is asserted by pipAppLayerAlwaysVisible().
+ // But the internal states of activity don't need to follow that, such as a temporary
+ // visibility state can be changed quickly outside a transaction so the test doesn't
+ // detect that. Hence, skip the case to avoid restricting the internal implementation.
+ Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+ super.pipAppWindowAlwaysVisible()
+ }
+
+ @Presubmit
+ @Test
override fun pipAppLayerAlwaysVisible() {
if (!flicker.scenario.isGesturalNavigation) super.pipAppLayerAlwaysVisible()
else {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
new file mode 100644
index 0000000..e133443
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerBuilder
+import com.android.server.wm.flicker.FlickerTest
+import com.android.server.wm.flicker.FlickerTestFactory
+import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import com.android.server.wm.traces.common.service.PlatformConsts
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/** Test minimizing a pip window via pinch in gesture. */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipPinchInTest(flicker: FlickerTest) : PipTransition(flicker) {
+ override val transition: FlickerBuilder.() -> Unit
+ get() = buildTransition { transitions { pipApp.pinchInPipWindow(wmHelper, 0.4f, 30) } }
+
+ /** Checks that the visible region area of [pipApp] always decreases during the animation. */
+ @Postsubmit
+ @Test
+ fun pipLayerAreaDecreases() {
+ flicker.assertLayers {
+ val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+ pipLayerList.zipWithNext { previous, current ->
+ current.visibleRegion.notBiggerThan(previous.visibleRegion.region)
+ }
+ }
+ }
+
+ companion object {
+ /**
+ * Creates the test configurations.
+ *
+ * See [FlickerTestFactory.nonRotationTests] for configuring screen orientation and
+ * navigation modes.
+ */
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTest> {
+ return FlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+ )
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index ce31aac..415c270 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -18,7 +18,7 @@
import android.app.Instrumentation
import android.content.Intent
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerBuilder
import com.android.server.wm.flicker.FlickerTest
import com.android.server.wm.flicker.helpers.PipAppHelper
@@ -80,7 +80,7 @@
}
}
- @Postsubmit
+ @Presubmit
@Test
fun hasAtMostOnePipDismissOverlayWindow() {
val matcher = ComponentNameMatcher("", "pip-dismiss-overlay")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index c08ad69..70a1523 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.splitscreen
+import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
@@ -136,7 +137,7 @@
}
/** {@inheritDoc} */
- @Presubmit
+ @FlakyTest(bugId = 264241018)
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index ff1d2990..d5bb901 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -28,9 +28,11 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -82,13 +84,14 @@
@Mock
SyncTransactionQueue mSyncQueue;
@Mock
- TaskViewTransitions mTaskViewTransitions;
+ Transitions mTransitions;
SurfaceSession mSession;
SurfaceControl mLeash;
Context mContext;
TaskView mTaskView;
+ TaskViewTransitions mTaskViewTransitions;
@Before
public void setUp() {
@@ -118,6 +121,10 @@
return null;
}).when(mSyncQueue).runInSync(any());
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ doReturn(true).when(mTransitions).isRegistered();
+ }
+ mTaskViewTransitions = spy(new TaskViewTransitions(mTransitions));
mTaskView = new TaskView(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue);
mTaskView.setListener(mExecutor, mViewListener);
}
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 65e1ea8..0bb809d 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
@@ -29,11 +29,13 @@
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
+import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -45,6 +47,8 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
@@ -57,6 +61,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -65,6 +70,8 @@
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.split.SplitLayout;
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.Transitions;
import org.junit.Before;
@@ -98,11 +105,7 @@
@Mock
private DisplayInsetsController mDisplayInsetsController;
@Mock
- private Transitions mTransitions;
- @Mock
private TransactionPool mTransactionPool;
- @Mock
- private ShellExecutor mMainExecutor;
private final Rect mBounds1 = new Rect(10, 20, 30, 40);
private final Rect mBounds2 = new Rect(5, 10, 15, 20);
@@ -112,11 +115,16 @@
private SurfaceControl mRootLeash;
private ActivityManager.RunningTaskInfo mRootTask;
private StageCoordinator mStageCoordinator;
+ private Transitions mTransitions;
+ private final TestShellExecutor mMainExecutor = new TestShellExecutor();
+ private final ShellExecutor mAnimExecutor = new TestShellExecutor();
+ private final Handler mMainHandler = new Handler(Looper.getMainLooper());
@Before
@UiThreadTest
public void setup() {
MockitoAnnotations.initMocks(this);
+ mTransitions = createTestTransitions();
mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
@@ -329,7 +337,20 @@
mStageCoordinator.onFoldedStateChanged(true);
- verify(mStageCoordinator).onSplitScreenExit();
- verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
+ } else {
+ verify(mStageCoordinator).onSplitScreenExit();
+ verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
+ }
+ }
+
+ private Transitions createTestTransitions() {
+ ShellInit shellInit = new ShellInit(mMainExecutor);
+ final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
+ mTaskOrganizer, mTransactionPool, mock(DisplayController.class), mMainExecutor,
+ mMainHandler, mAnimExecutor);
+ shellInit.init();
+ return t;
}
}
diff --git a/libs/androidfw/ConfigDescription.cpp b/libs/androidfw/ConfigDescription.cpp
index 93a7d17..cf2fd6f 100644
--- a/libs/androidfw/ConfigDescription.cpp
+++ b/libs/androidfw/ConfigDescription.cpp
@@ -21,6 +21,7 @@
#include "androidfw/Util.h"
#include <string>
+#include <string_view>
#include <vector>
namespace android {
@@ -38,11 +39,11 @@
return true;
}
const char* c = name;
- if (tolower(*c) != 'm') return false;
+ if (*c != 'm') return false;
c++;
- if (tolower(*c) != 'c') return false;
+ if (*c != 'c') return false;
c++;
- if (tolower(*c) != 'c') return false;
+ if (*c != 'c') return false;
c++;
const char* val = c;
@@ -68,11 +69,11 @@
return true;
}
const char* c = name;
- if (tolower(*c) != 'm') return false;
+ if (*c != 'm') return false;
c++;
- if (tolower(*c) != 'n') return false;
+ if (*c != 'n') return false;
c++;
- if (tolower(*c) != 'c') return false;
+ if (*c != 'c') return false;
c++;
const char* val = c;
@@ -93,6 +94,23 @@
return true;
}
+static bool parseGrammaticalInflection(const std::string& name, ResTable_config* out) {
+ using namespace std::literals;
+ if (name == "feminine"sv) {
+ if (out) out->grammaticalInflection = ResTable_config::GRAMMATICAL_GENDER_FEMININE;
+ return true;
+ }
+ if (name == "masculine"sv) {
+ if (out) out->grammaticalInflection = ResTable_config::GRAMMATICAL_GENDER_MASCULINE;
+ return true;
+ }
+ if (name == "neuter"sv) {
+ if (out) out->grammaticalInflection = ResTable_config::GRAMMATICAL_GENDER_NEUTER;
+ return true;
+ }
+ return false;
+}
+
static bool parseLayoutDirection(const char* name, ResTable_config* out) {
if (strcmp(name, kWildcardName) == 0) {
if (out)
@@ -678,6 +696,13 @@
}
}
+ if (parseGrammaticalInflection(*part_iter, &config)) {
+ ++part_iter;
+ if (part_iter == parts_end) {
+ goto success;
+ }
+ }
+
if (parseLayoutDirection(part_iter->c_str(), &config)) {
++part_iter;
if (part_iter == parts_end) {
@@ -832,11 +857,13 @@
void ConfigDescription::ApplyVersionForCompatibility(
ConfigDescription* config) {
uint16_t min_sdk = 0;
- if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
+ if (config->grammaticalInflection != 0) {
+ min_sdk = SDK_U;
+ } else if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
== ResTable_config::UI_MODE_TYPE_VR_HEADSET ||
config->colorMode & ResTable_config::MASK_WIDE_COLOR_GAMUT ||
config->colorMode & ResTable_config::MASK_HDR) {
- min_sdk = SDK_O;
+ min_sdk = SDK_O;
} else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
min_sdk = SDK_MARSHMALLOW;
} else if (config->density == ResTable_config::DENSITY_ANY) {
@@ -913,6 +940,7 @@
if (country[0] || o.country[0]) return (!o.country[0]);
// Script and variant require either a language or country, both of which
// have higher precedence.
+ if (grammaticalInflection || o.grammaticalInflection) return !o.grammaticalInflection;
if ((screenLayout | o.screenLayout) & MASK_LAYOUTDIR) {
return !(o.screenLayout & MASK_LAYOUTDIR);
}
@@ -971,6 +999,7 @@
// The values here can be found in ResTable_config#match. Density and range
// values can't lead to conflicts, and are ignored.
return !pred(mcc, o.mcc) || !pred(mnc, o.mnc) || !pred(locale, o.locale) ||
+ !pred(grammaticalInflection, o.grammaticalInflection) ||
!pred(screenLayout & MASK_LAYOUTDIR,
o.screenLayout & MASK_LAYOUTDIR) ||
!pred(screenLayout & MASK_SCREENLONG,
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 1fed206..29d33da 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2105,6 +2105,9 @@
return 1;
}
+ if (grammaticalInflection != o.grammaticalInflection) {
+ return grammaticalInflection < o.grammaticalInflection ? -1 : 1;
+ }
if (screenType != o.screenType) {
return (screenType > o.screenType) ? 1 : -1;
}
@@ -2153,7 +2156,9 @@
if (diff > 0) {
return 1;
}
-
+ if (grammaticalInflection != o.grammaticalInflection) {
+ return grammaticalInflection < o.grammaticalInflection ? -1 : 1;
+ }
if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1;
}
@@ -2223,6 +2228,7 @@
if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
+ if (grammaticalInflection != o.grammaticalInflection) diffs |= CONFIG_GRAMMATICAL_GENDER;
const int diff = compareLocales(*this, o);
if (diff) diffs |= CONFIG_LOCALE;
@@ -2289,6 +2295,13 @@
}
}
+ if (grammaticalInflection || o.grammaticalInflection) {
+ if (grammaticalInflection != o.grammaticalInflection) {
+ if (!grammaticalInflection) return false;
+ if (!o.grammaticalInflection) return true;
+ }
+ }
+
if (screenLayout || o.screenLayout) {
if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0) {
if (!(screenLayout & MASK_LAYOUTDIR)) return false;
@@ -2555,6 +2568,13 @@
return true;
}
+ if (grammaticalInflection || o.grammaticalInflection) {
+ if (grammaticalInflection != o.grammaticalInflection
+ && requested->grammaticalInflection) {
+ return !!grammaticalInflection;
+ }
+ }
+
if (screenLayout || o.screenLayout) {
if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0
&& (requested->screenLayout & MASK_LAYOUTDIR)) {
@@ -2854,6 +2874,10 @@
}
}
+ if (grammaticalInflection && grammaticalInflection != settings.grammaticalInflection) {
+ return false;
+ }
+
if (screenConfig != 0) {
const int layoutDir = screenLayout&MASK_LAYOUTDIR;
const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
@@ -3267,6 +3291,15 @@
appendDirLocale(res);
+ if ((grammaticalInflection & GRAMMATICAL_INFLECTION_GENDER_MASK) != 0) {
+ if (res.size() > 0) res.append("-");
+ switch (grammaticalInflection & GRAMMATICAL_INFLECTION_GENDER_MASK) {
+ case GRAMMATICAL_GENDER_NEUTER: res.append("neuter"); break;
+ case GRAMMATICAL_GENDER_FEMININE: res.append("feminine"); break;
+ case GRAMMATICAL_GENDER_MASCULINE: res.append("masculine"); break;
+ }
+ }
+
if ((screenLayout&MASK_LAYOUTDIR) != 0) {
if (res.size() > 0) res.append("-");
switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) {
diff --git a/libs/androidfw/include/androidfw/ConfigDescription.h b/libs/androidfw/include/androidfw/ConfigDescription.h
index 71087cd..7fbd7c0 100644
--- a/libs/androidfw/include/androidfw/ConfigDescription.h
+++ b/libs/androidfw/include/androidfw/ConfigDescription.h
@@ -53,6 +53,12 @@
SDK_O = 26,
SDK_O_MR1 = 27,
SDK_P = 28,
+ SDK_Q = 29,
+ SDK_R = 30,
+ SDK_S = 31,
+ SDK_S_V2 = 32,
+ SDK_TIRAMISU = 33,
+ SDK_U = 34,
};
/*
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 52321da..631bda4 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1071,15 +1071,32 @@
NAVHIDDEN_NO = ACONFIGURATION_NAVHIDDEN_NO << SHIFT_NAVHIDDEN,
NAVHIDDEN_YES = ACONFIGURATION_NAVHIDDEN_YES << SHIFT_NAVHIDDEN,
};
-
- union {
- struct {
- uint8_t keyboard;
- uint8_t navigation;
- uint8_t inputFlags;
- uint8_t inputPad0;
+
+ enum {
+ GRAMMATICAL_GENDER_ANY = ACONFIGURATION_GRAMMATICAL_GENDER_ANY,
+ GRAMMATICAL_GENDER_NEUTER = ACONFIGURATION_GRAMMATICAL_GENDER_NEUTER,
+ GRAMMATICAL_GENDER_FEMININE = ACONFIGURATION_GRAMMATICAL_GENDER_FEMININE,
+ GRAMMATICAL_GENDER_MASCULINE = ACONFIGURATION_GRAMMATICAL_GENDER_MASCULINE,
+ GRAMMATICAL_INFLECTION_GENDER_MASK = 0b11,
+ };
+
+ struct {
+ union {
+ struct {
+ uint8_t keyboard;
+ uint8_t navigation;
+ uint8_t inputFlags;
+ uint8_t inputFieldPad0;
+ };
+ struct {
+ uint32_t input : 24;
+ uint32_t inputFullPad0 : 8;
+ };
+ struct {
+ uint8_t grammaticalInflectionPad0[3];
+ uint8_t grammaticalInflection;
+ };
};
- uint32_t input;
};
enum {
@@ -1263,6 +1280,7 @@
CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR,
CONFIG_SCREEN_ROUND = ACONFIGURATION_SCREEN_ROUND,
CONFIG_COLOR_MODE = ACONFIGURATION_COLOR_MODE,
+ CONFIG_GRAMMATICAL_GENDER = ACONFIGURATION_GRAMMATICAL_GENDER,
};
// Compare two configuration, returning CONFIG_* flags set for each value
diff --git a/libs/androidfw/tests/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp
index 8fed0a4..f5c01e5 100644
--- a/libs/androidfw/tests/ConfigDescription_test.cpp
+++ b/libs/androidfw/tests/ConfigDescription_test.cpp
@@ -154,4 +154,22 @@
EXPECT_FALSE(ParseConfigOrDie("600x400").ConflictsWith(ParseConfigOrDie("300x200")));
}
+TEST(ConfigDescriptionTest, TestGrammaticalGenderQualifier) {
+ ConfigDescription config;
+ EXPECT_TRUE(TestParse("feminine", &config));
+ EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_FEMININE, config.grammaticalInflection);
+ EXPECT_EQ(SDK_U, config.sdkVersion);
+ EXPECT_EQ(std::string("feminine-v34"), config.toString().string());
+
+ EXPECT_TRUE(TestParse("masculine", &config));
+ EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_MASCULINE, config.grammaticalInflection);
+ EXPECT_EQ(SDK_U, config.sdkVersion);
+ EXPECT_EQ(std::string("masculine-v34"), config.toString().string());
+
+ EXPECT_TRUE(TestParse("neuter", &config));
+ EXPECT_EQ(android::ResTable_config::GRAMMATICAL_GENDER_NEUTER, config.grammaticalInflection);
+ EXPECT_EQ(SDK_U, config.sdkVersion);
+ EXPECT_EQ(std::string("neuter-v34"), config.toString().string());
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
index 698c36f..5477621 100644
--- a/libs/androidfw/tests/Config_test.cpp
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -205,4 +205,18 @@
EXPECT_EQ(defaultConfig.diff(hdrConfig), ResTable_config::CONFIG_COLOR_MODE);
}
+TEST(ConfigTest, GrammaticalGender) {
+ ResTable_config defaultConfig = {};
+ ResTable_config masculine = {};
+ masculine.grammaticalInflection = ResTable_config::GRAMMATICAL_GENDER_MASCULINE;
+
+ EXPECT_EQ(defaultConfig.diff(masculine), ResTable_config::CONFIG_GRAMMATICAL_GENDER);
+
+ ResTable_config feminine = {};
+ feminine.grammaticalInflection = ResTable_config::GRAMMATICAL_GENDER_FEMININE;
+
+ EXPECT_EQ(defaultConfig.diff(feminine), ResTable_config::CONFIG_GRAMMATICAL_GENDER);
+ EXPECT_EQ(masculine.diff(feminine), ResTable_config::CONFIG_GRAMMATICAL_GENDER);
+}
+
} // namespace android.
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index aeead5e..9112b1b 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -376,7 +376,10 @@
"jni/text/TextShaper.cpp",
],
- header_libs: ["android_graphics_jni_headers"],
+ header_libs: [
+ "android_graphics_jni_headers",
+ "libnativewindow_headers",
+ ],
include_dirs: [
"external/skia/include/private",
@@ -392,10 +395,14 @@
"libbase",
"libcutils",
"libharfbuzz_ng",
+ "libimage_io",
+ "libjpeg",
+ "libjpegdecoder",
+ "libjpegencoder",
+ "libjpegrecoverymap",
"liblog",
"libminikin",
"libz",
- "libjpeg",
],
static_libs: [
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 6affc6a..b0896da 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -138,7 +138,9 @@
skpCaptureEnabled = debuggingEnabled && base::GetBoolProperty(PROPERTY_CAPTURE_SKP_ENABLED, false);
SkAndroidFrameworkTraceUtil::setEnableTracing(
- base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
+ base::GetBoolProperty(PROPERTY_SKIA_TRACING_ENABLED, false));
+ SkAndroidFrameworkTraceUtil::setUsePerfettoTrackEvents(
+ base::GetBoolProperty(PROPERTY_SKIA_USE_PERFETTO_TRACK_EVENTS, false));
runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 96a5176..ed7175e 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -143,9 +143,32 @@
#define PROPERTY_CAPTURE_SKP_ENABLED "debug.hwui.capture_skp_enabled"
/**
- * Allows to record Skia drawing commands with systrace.
+ * Allows broad recording of Skia drawing commands.
+ *
+ * If disabled, a very minimal set of trace events *may* be recorded.
+ * If enabled, a much broader set of trace events *may* be recorded.
+ *
+ * In either case, trace events are only recorded if an appropriately configured tracing session is
+ * active.
+ *
+ * Use debug.hwui.skia_use_perfetto_track_events to determine if ATrace (default) or Perfetto is
+ * used as the tracing backend.
*/
-#define PROPERTY_SKIA_ATRACE_ENABLED "debug.hwui.skia_atrace_enabled"
+#define PROPERTY_SKIA_TRACING_ENABLED "debug.hwui.skia_tracing_enabled"
+
+/**
+ * Switches Skia's tracing to use Perfetto's Track Event system instead of ATrace.
+ *
+ * If disabled, ATrace will be used by default, which will record trace events from any of Skia's
+ * tracing categories if overall system tracing is active and the "gfx" and "view" ATrace categories
+ * are enabled.
+ *
+ * If enabled, then Perfetto's Track Event system will be used instead, which will only record if an
+ * active Perfetto tracing session is targeting the correct apps and Skia tracing categories with
+ * the Track Event data source enabled. This approach may be used to selectively filter out
+ * undesired Skia tracing categories, and events will contain more data fields.
+ */
+#define PROPERTY_SKIA_USE_PERFETTO_TRACK_EVENTS "debug.hwui.skia_use_perfetto_track_events"
/**
* Defines how many frames in a sequence to capture.
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index e1030b0..3f7c4f0 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -21,6 +21,7 @@
#include <hwui/Paint.h>
#include <experimental/type_traits>
+#include <log/log.h>
#include <utility>
#include "SkAndroidFrameworkUtils.h"
@@ -34,7 +35,6 @@
#include "SkImageFilter.h"
#include "SkImageInfo.h"
#include "SkLatticeIter.h"
-#include "SkMath.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkRRect.h"
@@ -45,6 +45,7 @@
#include "SkVertices.h"
#include "VectorDrawable.h"
#include "include/gpu/GpuTypes.h" // from Skia
+#include "include/gpu/GrDirectContext.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/FunctorDrawable.h"
@@ -66,16 +67,24 @@
template <typename S, typename... Rest>
static void copy_v(void* dst, const S* src, int n, Rest&&... rest) {
- SkASSERTF(((uintptr_t)dst & (alignof(S) - 1)) == 0,
- "Expected %p to be aligned for at least %zu bytes.", dst, alignof(S));
- sk_careful_memcpy(dst, src, n * sizeof(S));
- copy_v(SkTAddOffset<void>(dst, n * sizeof(S)), std::forward<Rest>(rest)...);
+ LOG_FATAL_IF(((uintptr_t)dst & (alignof(S) - 1)) != 0,
+ "Expected %p to be aligned for at least %zu bytes.",
+ dst, alignof(S));
+ // If n is 0, there is nothing to copy into dst from src.
+ if (n > 0) {
+ memcpy(dst, src, n * sizeof(S));
+ dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(dst) + n * sizeof(S));
+ }
+ // Repeat for the next items, if any
+ copy_v(dst, std::forward<Rest>(rest)...);
}
// Helper for getting back at arrays which have been copy_v'd together after an Op.
template <typename D, typename T>
static const D* pod(const T* op, size_t offset = 0) {
- return SkTAddOffset<const D>(op + 1, offset);
+ return reinterpret_cast<const D*>(
+ reinterpret_cast<const uint8_t*>(op + 1) + offset);
}
namespace {
@@ -458,12 +467,43 @@
struct DrawMesh final : Op {
static const auto kType = Type::DrawMesh;
DrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
- : mesh(mesh), blender(std::move(blender)), paint(paint) {}
+ : cpuMesh(mesh), blender(std::move(blender)), paint(paint) {
+ isGpuBased = false;
+ }
- SkMesh mesh;
+ SkMesh cpuMesh;
+ mutable SkMesh gpuMesh;
sk_sp<SkBlender> blender;
SkPaint paint;
- void draw(SkCanvas* c, const SkMatrix&) const { c->drawMesh(mesh, blender, paint); }
+ mutable bool isGpuBased;
+ mutable GrDirectContext::DirectContextID contextId;
+ void draw(SkCanvas* c, const SkMatrix&) const {
+ GrDirectContext* directContext = c->recordingContext()->asDirectContext();
+ GrDirectContext::DirectContextID id = directContext->directContextID();
+ if (!isGpuBased || contextId != id) {
+ sk_sp<SkMesh::VertexBuffer> vb =
+ SkMesh::CopyVertexBuffer(directContext, cpuMesh.refVertexBuffer());
+ if (!cpuMesh.indexBuffer()) {
+ gpuMesh = SkMesh::Make(cpuMesh.refSpec(), cpuMesh.mode(), vb, cpuMesh.vertexCount(),
+ cpuMesh.vertexOffset(), cpuMesh.refUniforms(),
+ cpuMesh.bounds())
+ .mesh;
+ } else {
+ sk_sp<SkMesh::IndexBuffer> ib =
+ SkMesh::CopyIndexBuffer(directContext, cpuMesh.refIndexBuffer());
+ gpuMesh = SkMesh::MakeIndexed(cpuMesh.refSpec(), cpuMesh.mode(), vb,
+ cpuMesh.vertexCount(), cpuMesh.vertexOffset(), ib,
+ cpuMesh.indexCount(), cpuMesh.indexOffset(),
+ cpuMesh.refUniforms(), cpuMesh.bounds())
+ .mesh;
+ }
+
+ isGpuBased = true;
+ contextId = id;
+ }
+
+ c->drawMesh(gpuMesh, blender, paint);
+ }
};
struct DrawAtlas final : Op {
static const auto kType = Type::DrawAtlas;
@@ -613,7 +653,7 @@
template <typename T, typename... Args>
void* DisplayListData::push(size_t pod, Args&&... args) {
size_t skip = SkAlignPtr(sizeof(T) + pod);
- SkASSERT(skip < (1 << 24));
+ LOG_FATAL_IF(skip >= (1 << 24));
if (fUsed + skip > fReserved) {
static_assert(is_power_of_two(SKLITEDL_PAGE),
"This math needs updating for non-pow2.");
@@ -622,7 +662,7 @@
fBytes.realloc(fReserved);
LOG_ALWAYS_FATAL_IF(fBytes.get() == nullptr, "realloc(%zd) failed", fReserved);
}
- SkASSERT(fUsed + skip <= fReserved);
+ LOG_FATAL_IF((fUsed + skip) > fReserved);
auto op = (T*)(fBytes.get() + fUsed);
fUsed += skip;
new (op) T{std::forward<Args>(args)...};
@@ -752,7 +792,7 @@
int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0;
size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) +
fs * sizeof(SkColor);
- SkASSERT(lattice.fBounds);
+ LOG_FATAL_IF(!lattice.fBounds);
void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds,
dst, filter, paint, palette);
copy_v(pod, lattice.fXDivs, xs, lattice.fYDivs, ys, lattice.fColors, fs, lattice.fRectTypes,
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index af8bd26..1e0c359 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -19,6 +19,8 @@
#include <SkAndroidFrameworkUtils.h>
#include <SkAnimatedImage.h>
#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
#include <SkCanvasPriv.h>
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
@@ -35,7 +37,6 @@
#include <SkRect.h>
#include <SkRefCnt.h>
#include <SkShader.h>
-#include <SkTemplates.h>
#include <SkTextBlob.h>
#include <SkVertices.h>
@@ -45,13 +46,14 @@
#include "CanvasProperty.h"
#include "NinePatchUtils.h"
-#include "SkBlendMode.h"
#include "VectorDrawable.h"
#include "hwui/Bitmap.h"
#include "hwui/MinikinUtils.h"
#include "hwui/PaintFilter.h"
+#include <log/log.h>
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/HolePunch.h"
+#include <ui/FatVector.h>
namespace android {
@@ -248,7 +250,7 @@
? static_cast<const SaveRec*>(&mSaveStack->back())
: nullptr;
int currentSaveCount = mCanvas->getSaveCount();
- SkASSERT(!rec || currentSaveCount >= rec->saveCount);
+ LOG_FATAL_IF(!(!rec || currentSaveCount >= rec->saveCount));
return (rec && rec->saveCount == currentSaveCount) ? rec : nullptr;
}
@@ -298,7 +300,7 @@
// Applies and optionally removes all clips >= index.
void SkiaCanvas::applyPersistentClips(size_t clipStartIndex) {
- SkASSERT(clipStartIndex <= mClipStack.size());
+ LOG_FATAL_IF(clipStartIndex > mClipStack.size());
const auto begin = mClipStack.cbegin() + clipStartIndex;
const auto end = mClipStack.cend();
@@ -646,7 +648,7 @@
texsPtr += 1;
y += dy;
}
- SkASSERT(texsPtr - texs == ptCount);
+ LOG_FATAL_IF((texsPtr - texs) != ptCount);
}
// cons up indices
@@ -669,14 +671,14 @@
// bump to the next row
index += 1;
}
- SkASSERT(indexPtr - indices == indexCount);
+ LOG_FATAL_IF((indexPtr - indices) != indexCount);
}
// double-check that we have legal indices
-#ifdef SK_DEBUG
+#if !defined(NDEBUG)
{
for (int i = 0; i < indexCount; i++) {
- SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
+ LOG_FATAL_IF((unsigned)indices[i] >= (unsigned)ptCount);
}
}
#endif
@@ -718,10 +720,12 @@
numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
}
- SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
- SkAutoSTMalloc<25, SkColor> colors(numFlags);
+ // Most times, we do not have very many flags/colors, so the stack allocated part of
+ // FatVector will save us a heap allocation.
+ FatVector<SkCanvas::Lattice::RectType, 25> flags(numFlags);
+ FatVector<SkColor, 25> colors(numFlags);
if (numFlags > 0) {
- NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
+ NinePatchUtils::SetLatticeFlags(&lattice, flags.data(), numFlags, chunk, colors.data());
}
lattice.fBounds = nullptr;
diff --git a/libs/hwui/SkiaInterpolator.cpp b/libs/hwui/SkiaInterpolator.cpp
index 47bd0b9..b58f517 100644
--- a/libs/hwui/SkiaInterpolator.cpp
+++ b/libs/hwui/SkiaInterpolator.cpp
@@ -16,7 +16,6 @@
#include "SkiaInterpolator.h"
-#include "include/core/SkMath.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"
#include "include/private/SkFixed.h"
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index c98b87a..2f3e9bf 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -14,7 +14,6 @@
#include "SkColorSpace.h"
#include "SkEncodedImageFormat.h"
#include "SkImageInfo.h"
-#include "SkMath.h"
#include "SkPaint.h"
#include "SkPixelRef.h"
#include "SkRect.h"
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index c835849..f5cd793 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -8,13 +8,11 @@
#include <nativehelper/JNIHelp.h>
#include "GraphicsJNI.h"
-#include "include/private/SkTemplates.h" // SkTAddOffset
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColorSpace.h"
#include "SkFontMetrics.h"
#include "SkImageInfo.h"
-#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkPoint.h"
#include "SkRect.h"
@@ -22,6 +20,7 @@
#include "SkTypes.h"
#include <cutils/ashmem.h>
#include <hwui/Canvas.h>
+#include <log/log.h>
using namespace android;
@@ -491,7 +490,7 @@
void GraphicsJNI::set_metrics(JNIEnv* env, jobject metrics, const SkFontMetrics& skmetrics) {
if (metrics == nullptr) return;
- SkASSERT(env->IsInstanceOf(metrics, gFontMetrics_class));
+ LOG_FATAL_IF(!env->IsInstanceOf(metrics, gFontMetrics_class));
env->SetFloatField(metrics, gFontMetrics_top, SkScalarToFloat(skmetrics.fTop));
env->SetFloatField(metrics, gFontMetrics_ascent, SkScalarToFloat(skmetrics.fAscent));
env->SetFloatField(metrics, gFontMetrics_descent, SkScalarToFloat(skmetrics.fDescent));
@@ -505,7 +504,7 @@
int leading = SkScalarRoundToInt(skmetrics.fLeading);
if (metrics) {
- SkASSERT(env->IsInstanceOf(metrics, gFontMetricsInt_class));
+ LOG_FATAL_IF(!env->IsInstanceOf(metrics, gFontMetricsInt_class));
env->SetIntField(metrics, gFontMetricsInt_top, SkScalarFloorToInt(skmetrics.fTop));
env->SetIntField(metrics, gFontMetricsInt_ascent, ascent);
env->SetIntField(metrics, gFontMetricsInt_descent, descent);
@@ -714,7 +713,9 @@
mSkiaBitmap->info().height());
for (int y = 0; y < rowsToCopy; y++) {
memcpy(dst, mSkiaBitmap->getAddr(0, y), bytesToCopy);
- dst = SkTAddOffset<void>(dst, dstRowBytes);
+ // Cast to bytes in order to apply the dstRowBytes offset correctly.
+ dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(dst) + dstRowBytes);
}
recycledPixels->notifyPixelsChanged();
recycledPixels->unref();
diff --git a/libs/hwui/jni/Mesh.h b/libs/hwui/jni/Mesh.h
index 7a73f2d..61c2260 100644
--- a/libs/hwui/jni/Mesh.h
+++ b/libs/hwui/jni/Mesh.h
@@ -20,6 +20,7 @@
#include <SkMesh.h>
#include <jni.h>
+#include <log/log.h>
#include <utility>
#include "graphics_jni_helpers.h"
@@ -186,23 +187,24 @@
std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
const T& val) {
if (!fVar) {
- SkDEBUGFAIL("Assigning to missing variable");
+ LOG_FATAL("Assigning to missing variable");
} else if (sizeof(val) != fVar->sizeInBytes()) {
- SkDEBUGFAIL("Incorrect value size");
+ LOG_FATAL("Incorrect value size");
} else {
- memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset), &val,
- szeof(val));
+ void* dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+ memcpy(dst, &val, sizeof(val));
}
}
MeshUniform& operator=(const SkMatrix& val) {
if (!fVar) {
- SkDEBUGFAIL("Assigning to missing variable");
+ LOG_FATAL("Assigning to missing variable");
} else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
- SkDEBUGFAIL("Incorrect value size");
+ LOG_FATAL("Incorrect value size");
} else {
- float* data =
- SkTAddOffset<float>(fOwner->writableUniformData(), (ptrdiff_t)fVar->offset);
+ float* data = reinterpret_cast<float*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
data[0] = val.get(0);
data[1] = val.get(3);
data[2] = val.get(6);
@@ -220,14 +222,15 @@
bool set(const T val[], const int count) {
static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
if (!fVar) {
- SkDEBUGFAIL("Assigning to missing variable");
+ LOG_FATAL("Assigning to missing variable");
return false;
} else if (sizeof(T) * count != fVar->sizeInBytes()) {
- SkDEBUGFAIL("Incorrect value size");
+ LOG_FATAL("Incorrect value size");
return false;
} else {
- memcpy(SkTAddOffset<void>(fOwner->writableUniformData(), fVar->offset), val,
- sizeof(T) * count);
+ void* dst = reinterpret_cast<void*>(
+ reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+ memcpy(dst, val, sizeof(T) * count);
}
return true;
}
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index 1c5f126..80bca1f 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -1,3 +1,6 @@
+#undef LOG_TAG
+#define LOG_TAG "YuvToJpegEncoder"
+
#include "CreateJavaOutputStreamAdaptor.h"
#include "SkJPEGWriteUtility.h"
#include "SkStream.h"
@@ -235,6 +238,99 @@
}
///////////////////////////////////////////////////////////////////////////////
+using namespace android::recoverymap;
+
+jpegr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
+ switch (aDataSpace & ADataSpace::STANDARD_MASK) {
+ case ADataSpace::STANDARD_BT709:
+ return jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ case ADataSpace::STANDARD_DCI_P3:
+ return jpegr_color_gamut::JPEGR_COLORGAMUT_P3;
+ case ADataSpace::STANDARD_BT2020:
+ return jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ default:
+ jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
+ env->ThrowNew(IllegalArgumentException,
+ "The requested color gamut is not supported by JPEG/R.");
+ }
+
+ return jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED;
+}
+
+jpegr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNIEnv* env,
+ int aDataSpace) {
+ switch (aDataSpace & ADataSpace::TRANSFER_MASK) {
+ case ADataSpace::TRANSFER_ST2084:
+ return jpegr_transfer_function::JPEGR_TF_PQ;
+ case ADataSpace::TRANSFER_HLG:
+ return jpegr_transfer_function::JPEGR_TF_HLG;
+ default:
+ jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
+ env->ThrowNew(IllegalArgumentException,
+ "The requested HDR transfer function is not supported by JPEG/R.");
+ }
+
+ return jpegr_transfer_function::JPEGR_TF_UNSPECIFIED;
+}
+
+bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
+ SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace,
+ int width, int height, int jpegQuality) {
+ // Check SDR color space. Now we only support SRGB transfer function
+ if ((sdrColorSpace & ADataSpace::TRANSFER_MASK) != ADataSpace::TRANSFER_SRGB) {
+ jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
+ env->ThrowNew(IllegalArgumentException,
+ "The requested SDR color space is not supported. Transfer function must be SRGB");
+ return false;
+ }
+
+ jpegr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
+ jpegr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
+ jpegr_transfer_function hdrTransferFunction = findHdrTransferFunction(env, hdrColorSpace);
+
+ if (hdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
+ || sdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
+ || hdrTransferFunction == jpegr_transfer_function::JPEGR_TF_UNSPECIFIED) {
+ return false;
+ }
+
+ RecoveryMap recoveryMap;
+
+ jpegr_uncompressed_struct p010;
+ p010.data = hdr;
+ p010.width = width;
+ p010.height = height;
+ p010.colorGamut = hdrColorGamut;
+
+ jpegr_uncompressed_struct yuv420;
+ yuv420.data = sdr;
+ yuv420.width = width;
+ yuv420.height = height;
+ yuv420.colorGamut = sdrColorGamut;
+
+ jpegr_compressed_struct jpegR;
+ jpegR.maxLength = width * height * sizeof(uint8_t);
+
+ std::unique_ptr<uint8_t[]> jpegr_data = std::make_unique<uint8_t[]>(jpegR.maxLength);
+ jpegR.data = jpegr_data.get();
+
+ if (int success = recoveryMap.encodeJPEGR(&p010, &yuv420,
+ hdrTransferFunction,
+ &jpegR, jpegQuality, nullptr); success != android::OK) {
+ ALOGW("Encode JPEG/R failed, error code: %d.", success);
+ return false;
+ }
+
+ if (!stream->write(jpegR.data, jpegR.length)) {
+ ALOGW("Writing JPEG/R to stream failed.");
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
static jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv,
jint format, jint width, jint height, jintArray offsets,
jintArray strides, jint jpegQuality, jobject jstream,
@@ -258,11 +354,34 @@
delete strm;
return result;
}
+
+static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr,
+ jint hdrColorSpace, jbyteArray inSdr, jint sdrColorSpace,
+ jint width, jint height, jint quality, jobject jstream,
+ jbyteArray jstorage) {
+ jbyte* hdr = env->GetByteArrayElements(inHdr, NULL);
+ jbyte* sdr = env->GetByteArrayElements(inSdr, NULL);
+ SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+ P010Yuv420ToJpegREncoder encoder;
+
+ jboolean result = JNI_FALSE;
+ if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace,
+ width, height, quality)) {
+ result = JNI_TRUE;
+ }
+
+ env->ReleaseByteArrayElements(inHdr, hdr, 0);
+ env->ReleaseByteArrayElements(inSdr, sdr, 0);
+ delete strm;
+ return result;
+}
///////////////////////////////////////////////////////////////////////////////
static const JNINativeMethod gYuvImageMethods[] = {
{ "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z",
- (void*)YuvImage_compressToJpeg }
+ (void*)YuvImage_compressToJpeg },
+ { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B)Z",
+ (void*)YuvImage_compressToJpegR }
};
int register_android_graphics_YuvImage(JNIEnv* env)
diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h
index a69726b1..3d6d1f3 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.h
+++ b/libs/hwui/jni/YuvToJpegEncoder.h
@@ -1,6 +1,9 @@
#ifndef _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
#define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
+#include <android/data_space.h>
+#include <jpegrecoverymap/recoverymap.h>
+
extern "C" {
#include "jpeglib.h"
#include "jerror.h"
@@ -24,7 +27,7 @@
*
* @param stream The jpeg output stream.
* @param inYuv The input yuv data.
- * @param width Width of the the Yuv data in terms of pixels.
+ * @param width Width of the Yuv data in terms of pixels.
* @param height Height of the Yuv data in terms of pixels.
* @param offsets The offsets in each image plane with respect to inYuv.
* @param jpegQuality Picture quality in [0, 100].
@@ -71,4 +74,46 @@
uint8_t* vRows, int rowIndex, int width, int height);
};
+class P010Yuv420ToJpegREncoder {
+public:
+ /** Encode YUV data to jpeg/r, which is output to a stream.
+ * This method will call RecoveryMap::EncodeJPEGR() method. If encoding failed,
+ * Corresponding error code (defined in jpegrerrorcode.h) will be printed and this
+ * method will be terminated and return false.
+ *
+ * @param env JNI environment.
+ * @param stream The jpeg output stream.
+ * @param hdr The input yuv data (p010 format).
+ * @param hdrColorSpaceId color space id for the input hdr.
+ * @param sdr The input yuv data (yuv420p format).
+ * @param sdrColorSpaceId color space id for the input sdr.
+ * @param width Width of the Yuv data in terms of pixels.
+ * @param height Height of the Yuv data in terms of pixels.
+ * @param jpegQuality Picture quality in [0, 100].
+ * @return true if successfully compressed the stream.
+ */
+ bool encode(JNIEnv* env,
+ SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace,
+ int width, int height, int jpegQuality);
+
+ /** Map data space (defined in DataSpace.java and data_space.h) to the color gamut
+ * used in JPEG/R
+ *
+ * @param env JNI environment.
+ * @param aDataSpace data space defined in data_space.h.
+ * @return color gamut for JPEG/R.
+ */
+ static android::recoverymap::jpegr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
+
+ /** Map data space (defined in DataSpace.java and data_space.h) to the transfer function
+ * used in JPEG/R
+ *
+ * @param env JNI environment.
+ * @param aDataSpace data space defined in data_space.h.
+ * @return color gamut for JPEG/R.
+ */
+ static android::recoverymap::jpegr_transfer_function findHdrTransferFunction(
+ JNIEnv* env, int aDataSpace);
+};
+
#endif // _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index db449d6..08f0291 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -16,7 +16,6 @@
#include "SkiaRecordingCanvas.h"
#include "hwui/Paint.h"
-#include <include/private/SkTemplates.h> // SkAutoSTMalloc
#include <SkBlendMode.h>
#include <SkData.h>
#include <SkDrawable.h>
@@ -43,6 +42,8 @@
#include "pipeline/skia/VkFunctorDrawable.h"
#include "pipeline/skia/VkInteropFunctorDrawable.h"
#endif
+#include <log/log.h>
+#include <ui/FatVector.h>
namespace android {
namespace uirenderer {
@@ -55,7 +56,7 @@
void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, int width,
int height) {
mCurrentBarrier = nullptr;
- SkASSERT(mDisplayList.get() == nullptr);
+ LOG_FATAL_IF(mDisplayList.get() != nullptr);
if (renderNode) {
mDisplayList = renderNode->detachAvailableList();
@@ -285,10 +286,12 @@
numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
}
- SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
- SkAutoSTMalloc<25, SkColor> colors(numFlags);
+ // Most times, we do not have very many flags/colors, so the stack allocated part of
+ // FatVector will save us a heap allocation.
+ FatVector<SkCanvas::Lattice::RectType, 25> flags(numFlags);
+ FatVector<SkColor, 25> colors(numFlags);
if (numFlags > 0) {
- NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
+ NinePatchUtils::SetLatticeFlags(&lattice, flags.data(), numFlags, chunk, colors.data());
}
lattice.fBounds = nullptr;
diff --git a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
index 18cfce5..c019a8c 100644
--- a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
+++ b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
@@ -83,7 +83,9 @@
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
- mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ mPermissionIntent = PendingIntent.getBroadcast(this, 0,
+ new Intent(ACTION_USB_PERMISSION).setPackage(this.getPackageName()),
+ PendingIntent.FLAG_MUTABLE);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java
index ce73be1..3558dd5 100644
--- a/location/java/android/location/GnssAntennaInfo.java
+++ b/location/java/android/location/GnssAntennaInfo.java
@@ -347,8 +347,8 @@
@Override
public String toString() {
return "SphericalCorrections{"
- + "Corrections=" + Arrays.toString(mCorrections)
- + ", CorrectionUncertainties=" + Arrays.toString(mCorrectionUncertainties)
+ + "Corrections=" + Arrays.deepToString(mCorrections)
+ + ", CorrectionUncertainties=" + Arrays.deepToString(mCorrectionUncertainties)
+ ", DeltaTheta=" + getDeltaTheta()
+ ", DeltaPhi=" + getDeltaPhi()
+ '}';
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 4d3f05b..ceb3858 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -608,6 +608,40 @@
CHANNEL_OUT_LOW_FREQUENCY_2);
// CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
+ /** @hide */
+ @IntDef(flag = true, prefix = "CHANNEL_OUT", value = {
+ CHANNEL_OUT_FRONT_LEFT,
+ CHANNEL_OUT_FRONT_RIGHT,
+ CHANNEL_OUT_FRONT_CENTER,
+ CHANNEL_OUT_LOW_FREQUENCY,
+ CHANNEL_OUT_BACK_LEFT,
+ CHANNEL_OUT_BACK_RIGHT,
+ CHANNEL_OUT_FRONT_LEFT_OF_CENTER,
+ CHANNEL_OUT_FRONT_RIGHT_OF_CENTER,
+ CHANNEL_OUT_BACK_CENTER,
+ CHANNEL_OUT_SIDE_LEFT,
+ CHANNEL_OUT_SIDE_RIGHT,
+ CHANNEL_OUT_TOP_CENTER,
+ CHANNEL_OUT_TOP_FRONT_LEFT,
+ CHANNEL_OUT_TOP_FRONT_CENTER,
+ CHANNEL_OUT_TOP_FRONT_RIGHT,
+ CHANNEL_OUT_TOP_BACK_LEFT,
+ CHANNEL_OUT_TOP_BACK_CENTER,
+ CHANNEL_OUT_TOP_BACK_RIGHT,
+ CHANNEL_OUT_TOP_SIDE_LEFT,
+ CHANNEL_OUT_TOP_SIDE_RIGHT,
+ CHANNEL_OUT_BOTTOM_FRONT_LEFT,
+ CHANNEL_OUT_BOTTOM_FRONT_CENTER,
+ CHANNEL_OUT_BOTTOM_FRONT_RIGHT,
+ CHANNEL_OUT_LOW_FREQUENCY_2,
+ CHANNEL_OUT_FRONT_WIDE_LEFT,
+ CHANNEL_OUT_FRONT_WIDE_RIGHT,
+ CHANNEL_OUT_HAPTIC_B,
+ CHANNEL_OUT_HAPTIC_A
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelOut {}
+
/** Minimum value for sample rate,
* assuming AudioTrack and AudioRecord share the same limitations.
* @hide
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 24c5b41..813929e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -106,7 +106,6 @@
private Context mOriginalContext;
private Context mApplicationContext;
private @Nullable VirtualDeviceManager mVirtualDeviceManager; // Lazy initialized.
- private long mVolumeKeyUpTime;
private static final String TAG = "AudioManager";
private static final boolean DEBUG = false;
private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
@@ -911,7 +910,7 @@
int keyCode = event.getKeyCode();
if (keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_UP
&& keyCode != KeyEvent.KEYCODE_VOLUME_MUTE
- && mVolumeKeyUpTime + AudioSystem.PLAY_SOUND_DELAY > SystemClock.uptimeMillis()) {
+ && AudioSystem.PLAY_SOUND_DELAY > SystemClock.uptimeMillis()) {
/*
* The user has hit another key during the delay (e.g., 300ms)
* since the last volume key up, so cancel any sounds.
@@ -6443,6 +6442,20 @@
}
/**
+ * Returns the registered volume controller interface.
+ *
+ * @hide
+ */
+ @Nullable
+ public IVolumeController getVolumeController() {
+ try {
+ return getService().getVolumeController();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Notify audio manager about volume controller visibility changes.
* Currently limited to SystemUI.
*
@@ -6506,6 +6519,106 @@
/**
* @hide
+ * @return the RS2 value used for momentary exposure warnings
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public float getRs2Value() {
+ try {
+ return getService().getRs2Value();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Sets the RS2 value used for momentary exposure warnings
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void setRs2Value(float rs2Value) {
+ try {
+ getService().setRs2Value(rs2Value);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * @return the current computed sound dose value
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public float getCsd() {
+ try {
+ return getService().getCsd();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Sets the computed sound dose value to {@code csd}
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void setCsd(float csd) {
+ try {
+ getService().setCsd(csd);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Forces the computation of MEL values (used for CSD) on framework level. This will have the
+ * result of ignoring the MEL values computed on HAL level. Should only be used in testing
+ * since this can affect the certification of a device with EN50332-3 regulation.
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void forceUseFrameworkMel(boolean useFrameworkMel) {
+ try {
+ getService().forceUseFrameworkMel(useFrameworkMel);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Forces the computation of CSD on all output devices.
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
+ try {
+ getService().forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Returns whether CSD is enabled on this device.
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public boolean isCsdEnabled() {
+ try {
+ return getService().isCsdEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
* Sound dose warning at every 100% of dose during integration window
*/
public static final int CSD_WARNING_DOSE_REACHED_1X = 1;
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index f64e5cc..4d6ddfd 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -559,7 +559,8 @@
/**
* @hide
- * Return whether this player's output is spatialized
+ * Return whether this player's output is being processed by the spatializer effect backing
+ * the {@link android.media.Spatializer} implementation.
* @return true if spatialized, false if not or playback hasn't started
*/
@SystemApi
@@ -588,7 +589,7 @@
* the definitions for the <code>CHANNEL_OUT_*</code> values used for the mask's bitfield
*/
@SystemApi
- public int getChannelMask() {
+ public @AudioFormat.ChannelOut int getChannelMask() {
synchronized (mUpdateablePropLock) {
return (AudioFormat.convertNativeChannelMaskToOutMask(mFormatInfo.mNativeChannelMask));
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c06352c..5ba7891 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -260,6 +260,8 @@
void setVolumeController(in IVolumeController controller);
+ @nullable IVolumeController getVolumeController();
+
void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);
boolean isStreamAffectedByRingerMode(int streamType);
@@ -270,6 +272,27 @@
void lowerVolumeToRs1(String callingPackage);
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ float getRs2Value();
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ oneway void setRs2Value(float rs2Value);
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ float getCsd();
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ oneway void setCsd(float csd);
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ oneway void forceUseFrameworkMel(boolean useFrameworkMel);
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ oneway void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices);
+
+ @EnforcePermission("MODIFY_AUDIO_SYSTEM_SETTINGS")
+ boolean isCsdEnabled();
+
int setHdmiSystemAudioSupported(boolean on);
boolean isHdmiSystemAudioSupported();
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index fa74a9f..a7959c5 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -1515,6 +1515,16 @@
}
/**
+ * Returns the current {@link RoutingSessionInfo} associated to this controller.
+ */
+ @NonNull
+ public RoutingSessionInfo getRoutingSessionInfo() {
+ synchronized (mControllerLock) {
+ return mSessionInfo;
+ }
+ }
+
+ /**
* Gets the information about how volume is handled on the session.
*
* <p>Please note that you may not control the volume of the session even when you can
@@ -1873,13 +1883,6 @@
return result.toString();
}
- @NonNull
- RoutingSessionInfo getRoutingSessionInfo() {
- synchronized (mControllerLock) {
- return mSessionInfo;
- }
- }
-
void setRoutingSessionInfo(@NonNull RoutingSessionInfo info) {
synchronized (mControllerLock) {
mSessionInfo = info;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 1e270b1..40a4858 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -827,16 +827,18 @@
ringtoneUri = ContentProvider.maybeAddUserId(ringtoneUri, context.getUserId());
}
- final String mimeType = resolver.getType(ringtoneUri);
- if (mimeType == null) {
- Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
- + " ignored: failure to find mimeType (no access from this context?)");
- return;
- }
- if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
- Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
- + " ignored: associated mimeType:" + mimeType + " is not an audio type");
- return;
+ if (ringtoneUri != null) {
+ final String mimeType = resolver.getType(ringtoneUri);
+ if (mimeType == null) {
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
+ + " ignored: failure to find mimeType (no access from this context?)");
+ return;
+ }
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
+ Log.e(TAG, "setActualDefaultRingtoneUri for URI:" + ringtoneUri
+ + " ignored: associated mimeType:" + mimeType + " is not an audio type");
+ return;
+ }
}
Settings.System.putStringForUser(resolver, setting,
diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp
index 87fe9ed..b50514d 100644
--- a/native/android/configuration.cpp
+++ b/native/android/configuration.cpp
@@ -234,6 +234,14 @@
| ((value<<ResTable_config::SHIFT_LAYOUTDIR)&ResTable_config::MASK_LAYOUTDIR);
}
+int32_t AConfiguration_getGrammaticalGender(AConfiguration* config) {
+ return config->grammaticalInflection;
+}
+
+void AConfiguration_setGrammaticalGender(AConfiguration* config, int32_t value) {
+ config->grammaticalInflection = value & ResTable_config::GRAMMATICAL_INFLECTION_GENDER_MASK;
+}
+
// ----------------------------------------------------------------------
int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2) {
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index e89c8c9..e4b9b5d 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -42,6 +42,7 @@
AConfiguration_fromAssetManager;
AConfiguration_getCountry;
AConfiguration_getDensity;
+ AConfiguration_getGrammaticalGender; # introduced=UpsideDownCake
AConfiguration_getKeyboard;
AConfiguration_getKeysHidden;
AConfiguration_getLanguage;
@@ -66,6 +67,7 @@
AConfiguration_new;
AConfiguration_setCountry;
AConfiguration_setDensity;
+ AConfiguration_setGrammaticalGender; # introduced=UpsideDownCake
AConfiguration_setKeyboard;
AConfiguration_setKeysHidden;
AConfiguration_setLanguage;
diff --git a/omapi/OWNERS b/omapi/OWNERS
index 5682fd3..1dce1e0 100644
--- a/omapi/OWNERS
+++ b/omapi/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 456592
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
jackcwyu@google.com
diff --git a/omapi/java/android/se/OWNERS b/omapi/java/android/se/OWNERS
index 5682fd3..1dce1e0 100644
--- a/omapi/java/android/se/OWNERS
+++ b/omapi/java/android/se/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 456592
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
jackcwyu@google.com
diff --git a/omapi/java/android/se/omapi/OWNERS b/omapi/java/android/se/omapi/OWNERS
index 5682fd3..1dce1e0 100644
--- a/omapi/java/android/se/omapi/OWNERS
+++ b/omapi/java/android/se/omapi/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 456592
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
alisher@google.com
jackcwyu@google.com
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 3f86aba..8f9730a 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -34,8 +34,7 @@
android:label="@string/app_name"
android:directBootAware="true"
android:usesCleartextTraffic="true"
- android:icon="@mipmap/ic_launcher_android"
- android:debuggable="true">
+ android:icon="@mipmap/ic_launcher_android">
<receiver android:name="com.android.carrierdefaultapp.CarrierDefaultBroadcastReceiver"
android:exported="true">
<intent-filter>
diff --git a/packages/CarrierDefaultApp/res/values-af/strings.xml b/packages/CarrierDefaultApp/res/values-af/strings.xml
index b68377e..0e77826 100644
--- a/packages/CarrierDefaultApp/res/values-af/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-af/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Gaan in elk geval deur blaaier voort"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestasiehupstoot"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s beveel ’n prestasiehupstoot aan"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Koop ’n prestasiehupstoot sodat die netwerk beter werk"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie nou nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Bestuur"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop ’n prestasiehupstoot."</string>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
index 4d0c6d1..8ab8fbbb 100644
--- a/packages/CarrierDefaultApp/res/values-am/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"የአፈጻጸም ጭማሪ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s አፈጻጸምን መጨመር ይመክራል"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ይበልጥ ለተሻለ የአውታረ መረብ አፈጻጸም የአፈጻጸም ጭማሪ ይግዙ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"አሁን አይደለም"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"አስተዳድር"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"የአፈጻጸም ጭማሪ ይግዙ።"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
index 75dd352..55a7c0f 100644
--- a/packages/CarrierDefaultApp/res/values-ar/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المؤسسة المعروضة."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"المتابعة على أي حال عبر المتصفح"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تطبيق تعزيز الأداء"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"هناك اقتراح من \"%s\" بتعزيز الأداء"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"يمكنك شراء تطبيق لتعزيز الأداء من أجل الحصول على أداء أفضل للشبكة."</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"لاحقًا"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"إدارة"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"شراء تطبيق تعزيز الأداء"</string>
diff --git a/packages/CarrierDefaultApp/res/values-as/strings.xml b/packages/CarrierDefaultApp/res/values-as/strings.xml
index d299881a..755d28d 100644
--- a/packages/CarrierDefaultApp/res/values-as/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-as/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"তথাপিও ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"কাৰ্যক্ষমতা পৰিৱৰ্ধন"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%sএ এটা কাৰ্যক্ষমতা পৰিৱৰ্ধনৰ চুপাৰিছ কৰিছে"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"নেটৱৰ্কৰ উন্নত কাৰ্যক্ষমতা পাবলৈ কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এতিয়া নহয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"পৰিচালনা কৰক"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"এটা কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-az/strings.xml b/packages/CarrierDefaultApp/res/values-az/strings.xml
index cdda3a9..d8ee5b96 100644
--- a/packages/CarrierDefaultApp/res/values-az/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-az/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Hər bir halda brazuer ilə davam edin"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artırması"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s performans artırması tövsiyə edir"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Daha yaxşı şəbəkə performansı üçün performans artırması alın"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"İndi yox"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"İdarə edin"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artırması alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index 9cf6368..f4adf53 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje učinka"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s preporučuje poboljšanje učinka"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kupite poboljšanje učinka za mrežu"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje učinka."</string>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index d7b2bae..952a497 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Павышэнне прадукцыйнасці"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s рэкамендуе павысіць прадукцыйнасць"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Вы можаце павысіць прадукцыйнасць сеткі за дадатковую плату"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не цяпер"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Кіраваць"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Аплаціце павышэнне прадукцыйнасці."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
index 651277d..f055acc 100644
--- a/packages/CarrierDefaultApp/res/values-bg/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например страницата за вход може да не принадлежи на показаната организация."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продължаване през браузър въпреки това"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Увеличаване на ефективността"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s препоръчва пакет за увеличаване на ефективността"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Купете пакет за увеличаване на ефективността, за да подобрите мрежата"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управление"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете пакет за увеличаване на ефективността."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index c544531..5eb9e16 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"পারফর্ম্যান্স বুস্ট"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s পারফর্ম্যান্স বুস্ট ব্যবহার করার সাজেশন দেয়"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"আরও ভাল নেটওয়ার্ক পারফর্ম্যান্সের জন্য পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এখন নয়"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ম্যানেজ করুন"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 317f6f1..052713b 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pojačavanje performansi"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s preporučuje pojačavanje performansi"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kupite pojačavanje performansi radi boljih performansi mreže"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite pojačavanje performansi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index ee38e67..40181ef 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomana optimitzar el rendiment"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compra una optimització de rendiment perquè la xarxa funcioni millor"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-cs/strings.xml b/packages/CarrierDefaultApp/res/values-cs/strings.xml
index f479c48..d638272 100644
--- a/packages/CarrierDefaultApp/res/values-cs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-cs/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Přihlašovací stránka například nemusí patřit zobrazované organizaci."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Přesto pokračovat prostřednictvím prohlížeče"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšení výkonu"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s doporučuje zvýšení výkonu"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kupte si zvýšení výkonu pro lepší výkon sítě"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teď ne"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovat"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupte si zvýšení výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-da/strings.xml b/packages/CarrierDefaultApp/res/values-da/strings.xml
index 944942f..b1d6b08 100644
--- a/packages/CarrierDefaultApp/res/values-da/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-da/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsæt alligevel via browseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ydeevneboost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s anbefaler et ydeevneboost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Køb et ydeevneboost for at få et mere effektivt netværk"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Køb et ydeevneboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
index 7cdcca4..2124253 100644
--- a/packages/CarrierDefaultApp/res/values-de/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Trotzdem in einem Browser fortfahren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Leistungs-Boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s empfiehlt einen Leistungs-Boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Leistungs-Boost für eine bessere Netzwerkleistung erwerben"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nicht jetzt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Verwalten"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Leistungs-Boost erwerben."</string>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
index fbb76a8..58a8490 100644
--- a/packages/CarrierDefaultApp/res/values-el/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ενίσχυση απόδοσης"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"Η %s συνιστά ενίσχυση απόδοσης"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Αγοράστε μια ενίσχυση απόδοσης για καλύτερη απόδοση δικτύου"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Όχι τώρα"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Διαχείριση"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Αγοράστε μια ενίσχυση απόδοσης."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
index d91de31..de3baad 100644
--- a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommends a performance boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Buy a performance boost for better network performance"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
index 41e3951..07340fb 100644
--- a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommends a performance boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Buy a performance boost for better network performance"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
index d91de31..de3baad 100644
--- a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommends a performance boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Buy a performance boost for better network performance"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
index d91de31..de3baad 100644
--- a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommends a performance boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Buy a performance boost for better network performance"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
index ba9e1e9..f42fdb7 100644
--- a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommends a performance boost"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Buy a performance boost for better network performance"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
index 4a8b26a..23836ef 100644
--- a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos desde el navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomienda un aumento de rendimiento"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compra un aumento de rendimiento para mejorar el rendimiento de la red"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra un aumento de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
index 5eab185..5a405a9 100644
--- a/packages/CarrierDefaultApp/res/values-es/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos a través del navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mejora de rendimiento"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomienda una mejora de rendimiento"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compra una mejora de rendimiento para optimizar el rendimiento de red"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar una mejora de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
index 79c75222..9435c29 100644
--- a/packages/CarrierDefaultApp/res/values-et/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jätka siiski brauseris"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Jõudluse võimendus"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s soovitab jõudluse võimendust"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Ostke võrgu toimivuse parandamiseks jõudluse võimendus"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Mitte praegu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Haldamine"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Ostke jõudluse võimendus."</string>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index c8a6856..e47e5fe 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jarraitu arakatzailearen bidez, halere"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Errendimendu-hobekuntza"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s zerbitzuak errendimendu-hobekuntza bat erostea gomendatzen du"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Erosi errendimendu-hobekuntza bat sareko errendimendua hobetzeko"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Orain ez"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kudeatu"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Erosi errendimendu-hobekuntza bat."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index ba6f79c..60f8dbb 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"درهر صورت ازطریق مرورگر ادامه یابد"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویتکننده عملکرد"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s توصیه میکند از تقویتکننده عملکرد استفاده کنید"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"برای عملکرد بهتر شبکه، تقویتکننده عملکرد بخرید"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویتکننده عملکرد خریداری کنید."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fi/strings.xml b/packages/CarrierDefaultApp/res/values-fi/strings.xml
index b76284d..d4c612b 100644
--- a/packages/CarrierDefaultApp/res/values-fi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Jatka selaimen kautta"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Suorituskykyboosti"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s suosittelee suorituskykyboostia"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Paranna verkon suorituskykyä ostamalla suorituskykyboosti"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ei nyt"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Muuta"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Osta suorituskykyboosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
index 720def0..5ae71fd 100644
--- a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans un navigateur"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimiseur de performances"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommande un optimiseur de performances"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Acheter un optimiseur de performances pour améliorer les performances du réseau"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Plus tard"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un optimiseur de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr/strings.xml b/packages/CarrierDefaultApp/res/values-fr/strings.xml
index f5c75cd..bd711cc 100644
--- a/packages/CarrierDefaultApp/res/values-fr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr/strings.xml
@@ -14,10 +14,12 @@
<string name="ssl_error_warning" msgid="3127935140338254180">"Le réseau auquel vous essayez de vous connecter présente des problèmes de sécurité."</string>
<string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans le navigateur"</string>
- <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Amélioration des performances"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recommande d\'améliorer les performances"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Achetez une amélioration pour booster les performances du réseau"</string>
+ <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performances"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Pas maintenant"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
- <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez une amélioration des performances."</string>
+ <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un boost de performances."</string>
</resources>
diff --git a/packages/CarrierDefaultApp/res/values-gl/strings.xml b/packages/CarrierDefaultApp/res/values-gl/strings.xml
index 5111dfa..36f48e0 100644
--- a/packages/CarrierDefaultApp/res/values-gl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar igualmente co navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mellora de rendemento"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomenda unha mellora de rendemento"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compra unha mellora de rendemento para gozar dun mellor rendemento de rede"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora non"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Xestionar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar unha mellora de rendemento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index 8f919ed..da4f94f 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"તો પણ બ્રાઉઝર મારફતે ચાલુ રાખો"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"પર્ફોર્મન્સ બૂસ્ટ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s પર્ફોર્મન્સ બૂસ્ટનો સુઝાવ આપે છે"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"બહેતર નેટવર્ક પર્ફોર્મન્સ માટે પર્ફોર્મન્સ બૂસ્ટ ખરીદો"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"હમણાં નહીં"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"મેનેજ કરો"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"પર્ફોર્મન્સ બૂસ્ટ ખરીદો."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index 868bf48..6b12df7 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफ़ॉर्मेंस बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s परफ़ॉर्मेंस बूस्ट का सुझाव देता है"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"नेटवर्क की बेहतर परफ़ॉर्मेंस के लिए, कोई परफ़ॉर्मेंस बूस्ट खरीदें"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अभी नहीं"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"मैनेज करें"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"कोई परफ़ॉर्मेंस बूस्ट खरीदें."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
index b2b9232..96d8c3c 100644
--- a/packages/CarrierDefaultApp/res/values-hr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi putem preglednika"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje izvedbe"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s preporučuje poboljšanje izvedbe"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kupite poboljšanje izvedbe za mrežu"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sad"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje izvedbe."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
index 753a1486..bd75210 100644
--- a/packages/CarrierDefaultApp/res/values-hu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Például lehetséges, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Folytatás ennek ellenére böngészőn keresztül"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Teljesítménynövelés"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"A(z) %s teljesítménynövelést javasol"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Vásároljon teljesítménynövelést a jobb hálózati élmény érdekében"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Most nem"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kezelés"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Vásároljon teljesítménynövelést."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
index 851a4fd..63bb75c 100644
--- a/packages/CarrierDefaultApp/res/values-hy/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Շարունակել դիտարկիչի միջոցով"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Արտադրողականության բարձրացում"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s հավելվածը խորհուրդ է տալիս գնել արտադրողականության բարձրացում"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ոչ հիմա"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Կառավարել"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց։"</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index c90365cd..ef04781 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Misalnya, halaman login mungkin bukan milik organisasi yang ditampilkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tetap lanjutkan melalui browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Penguat sinyal"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s merekomendasikan penguat sinyal"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Beli penguat sinyal untuk performa jaringan yang lebih baik"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Lain kali"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kelola"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli penguat sinyal."</string>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
index 6f49d9f..2a38941 100644
--- a/packages/CarrierDefaultApp/res/values-is/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Halda samt áfram í vafra"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Afkastaaukning"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s mælir með afkastaaukningu"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kauptu afkastaaukningu til að bæta afköst netkerfisins"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ekki núna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Stjórna"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kaupa afkastaaukningu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
index ab42972..a3f0017 100644
--- a/packages/CarrierDefaultApp/res/values-it/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continua comunque dal browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento di prestazioni"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s consiglia un aumento di prestazioni"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Acquista un aumento di prestazioni per migliorare le prestazioni della rete"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Non ora"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestisci"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Acquista un aumento di prestazioni."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index bd19569..8dc073c 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"המשך בכל זאת באמצעות דפדפן"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"שיפור ביצועים"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"יש המלצה של %s לשיפור הביצועים"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"קניית שיפור ביצועים לביצועי רשת טובים יותר"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"לא עכשיו"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ניהול"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"רכישת שיפור ביצועים."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 7d487b6..01aa0d7 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s がパフォーマンス ブーストを推奨しています"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ネットワーク パフォーマンスを高めるにはパフォーマンス ブーストを購入してください"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
index 95904b0..6640254 100644
--- a/packages/CarrierDefaultApp/res/values-ka/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"მაინც ბრაუზერში გაგრძელება"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ეფექტურობის გაძლიერება"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s–ის მიერ რეკომენდებულია ეფექტურობის გაძლიერება"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"შეიძინეთ ეფექტურობის გაძლიერება ქსელის მეტი ეფექტურობისათვის"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ახლა არა"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"მართვა"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ეფექტურობის გაძლიერების შეძენა."</string>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
index bb31815..2ce3285 100644
--- a/packages/CarrierDefaultApp/res/values-kk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Бәрібір браузер арқылы жалғастыру"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Өнімділікті арттыру"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s қызметі өнімділікті арттыру құралын ұсынады"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Желі өнімділігін жақсарту үшін өнімділікті арттыру құралын сатып алыңыз."</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Қазір емес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Басқару"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Өнімділікті арттыру құралын сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-km/strings.xml b/packages/CarrierDefaultApp/res/values-km/strings.xml
index 067339c..6608570 100644
--- a/packages/CarrierDefaultApp/res/values-km/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-km/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ឧទាហរណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ការបង្កើនប្រតិបត្តិការ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s ណែនាំឱ្យការបង្កើនប្រតិបត្តិការ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ទិញការបង្កើនប្រតិបត្តិការ ដើម្បីឱ្យប្រតិបត្តិការបណ្ដាញប្រសើរជាងមុន"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"កុំទាន់"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"គ្រប់គ្រង"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ទិញការបង្កើនប្រតិបត្តិការ។"</string>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index 8323d21..b3ce678 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿಲ್ಲದಿರಬಹುದು."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ಪರವಾಗಿಲ್ಲ, ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s, ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ಉತ್ತಮವಾದ ನೆಟ್ವರ್ಕ್ ಕಾರ್ಯಕ್ಷಮತೆಗಾಗಿ, ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ಈಗ ಬೇಡ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ನಿರ್ವಹಿಸಿ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ko/strings.xml b/packages/CarrierDefaultApp/res/values-ko/strings.xml
index 68f0f27..3a59d1a 100644
--- a/packages/CarrierDefaultApp/res/values-ko/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ko/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"브라우저를 통해 계속하기"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"성능 향상"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s에서 성능 향상 권장"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"더 나은 네트워크 성능을 위해 성능 향상을 구매하세요."</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"나중에"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"관리"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"성능 향상 구매"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index 7c5418e..368e706 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Иштин майнаптуулугун жогорулатуу"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s иштин майнаптуулугун жогорулатууну сунуштайт"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Иштин майнаптуулугун жогорулатып, тармакты ылдамдатыңыз"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Азыр эмес"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Тескөө"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Иштин майнаптуулугун жогорулатууну сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
index a72f9349..722a8c5 100644
--- a/packages/CarrierDefaultApp/res/values-lo/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ຕົວຢ່າງ, ໜ້າເຂົ້າສູ່ລະບົບອາດຈະບໍ່ແມ່ນຂອງອົງກອນທີ່ປາກົດ."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ດຳເນີນການຕໍ່ຜ່ານໂປຣແກຣມທ່ອງເວັບ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ເລັ່ງປະສິດທິພາບ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s ແນະນຳການເລັ່ງປະສິດທິພາບ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ຊື້ການເລັ່ງປະສິດທິພາບເພື່ອປະສິດທິພາບທີ່ດີຂຶ້ນຂອງເຄືອຂ່າຍ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ບໍ່ຟ້າວເທື່ອ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ຈັດການ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ຊື້ການເລັ່ງປະສິດທິພາບ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
index ef59d20..e8817ef 100644
--- a/packages/CarrierDefaultApp/res/values-lt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vis tiek tęsti naudojant naršyklę"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Našumo pagerinimas"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s rekomenduoja našumo pagerinimo paslaugą"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Įsigykite tinklo našumo pagerinimo paslaugą"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne dabar"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Tvarkyti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Įsigykite našumo pagerinimo paslaugą."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lv/strings.xml b/packages/CarrierDefaultApp/res/values-lv/strings.xml
index f08c7a7..dcf800e 100644
--- a/packages/CarrierDefaultApp/res/values-lv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Tomēr turpināt, izmantojot pārlūkprogrammu"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Veiktspējas uzlabojums"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s iesaka veiktspējas uzlabojumu"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Nopērciet veiktspējas uzlabojumu, lai uzlabotu tīkla veiktspēju"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Vēlāk"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pārvaldīt"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Iegādājieties veiktspējas uzlabojumu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
index abcc0cd..a110920 100644
--- a/packages/CarrierDefaultApp/res/values-mk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страницата за најавување може да не припаѓа на прикажаната организација."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Сепак продолжи преку прелистувач"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Засилување на изведбата"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s препорачува засилување на изведбата"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Купете засилување на изведбата за подобра изведба на мрежата"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управувајте"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете засилување на изведбата."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
index 4c9199b..0757149 100644
--- a/packages/CarrierDefaultApp/res/values-ml/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"പ്രകടന ബൂസ്റ്റ്"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s പ്രകടന ബൂസ്റ്റ് നിർദ്ദേശിക്കുന്നു"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"നെറ്റ്വർക്കിന്റെ മെച്ചപ്പെട്ട പ്രകടനത്തിന് ഒരു പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ഇപ്പോൾ വേണ്ട"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"മാനേജ് ചെയ്യുക"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
index 6f3115f..da7f90c 100644
--- a/packages/CarrierDefaultApp/res/values-mn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Жишээлбэл нэвтрэх хуудас нь харагдаж буй байгууллагынх биш байж болно."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ямар ч тохиолдолд хөтчөөр үргэлжлүүлэх"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Гүйцэтгэлийн идэвхжүүлэлт"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s гүйцэтгэлийн идэвхжүүлэлтийг зөвлөж байна"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Сүлжээний гүйцэтгэлийг сайжруулахын тулд гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Одоо биш"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Удирдах"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index 6aff1f7..ee8cbf7 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s परफॉर्मन्स बूस्टची शिफारस करतात"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"अधिक चांगल्या नेटवर्क परफॉर्मन्ससाठी परफॉर्मन्स बूस्ट खरेदी करा"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"आता नको"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापित करा"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"परफॉर्मन्स बूस्ट खरेदी करा."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ms/strings.xml b/packages/CarrierDefaultApp/res/values-ms/strings.xml
index e96d8e5..6134874 100644
--- a/packages/CarrierDefaultApp/res/values-ms/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ms/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Teruskan juga melalui penyemak imbas"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Peningkatan prestasi"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s mengesyorkan perangsang prestasi"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Beli perangsang prestasi untuk mendapatkan prestasi rangkaian yang lebih baik"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Bukan sekarang"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Urus"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli perangsang prestasi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
index ef87797..1386b292 100644
--- a/packages/CarrierDefaultApp/res/values-my/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ဥပမာ− ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှုမရှိခြင်း ဖြစ်နိုင်ပါသည်။"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"မည်သို့ပင်ဖြစ်စေ ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s က စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်သုံးရန် အကြံပြုသည်"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ပိုကောင်းသည့် ကွန်ရက်စွမ်းဆောင်ရည်အတွက် စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်ကို ဝယ်ယူပါ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ယခုမလုပ်ပါ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"စီမံရန်"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ် ဝယ်ယူရန်။"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index b619ed4..a283f01 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsett likevel via nettleseren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Bedre ytelse"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s anbefaler bedre ytelse"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kjøp bedre ytelse for å øke nettverksytelsen"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nå"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kjøp bedre ytelse."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 58106ff..527a4ce 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"पर्फर्मेन्स बुस्ट"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s पर्फर्मेन्स बुस्ट किन्न सिफारिस गर्छ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"नेटवर्कको पर्फर्मेन्स अझ राम्रो बनाउन पर्फर्मेन्स बुस्ट किन्नुहोस्"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अहिले होइन"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापन गर्नुहोस्"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"पर्फर्मेन्स बुस्ट किन्नुहोस्।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
index ff20613..8abf26be 100644
--- a/packages/CarrierDefaultApp/res/values-nl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Toch doorgaan via browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestatieboost"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s raadt een prestatieboost aan"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Koop een prestatieboost voor betere netwerkprestaties"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Niet nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Beheren"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop een prestatieboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-or/strings.xml b/packages/CarrierDefaultApp/res/values-or/strings.xml
index bbb9a67..48ce1c7 100644
--- a/packages/CarrierDefaultApp/res/values-or/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-or/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ହୋଇନଥାଇପାରେ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ବ୍ରାଉଜର୍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ପରଫରମାନ୍ସ ବୁଷ୍ଟ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ ପାଇଁ ସୁପାରିଶ କରେ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ଉନ୍ନତ ନେଟୱାର୍କ ପରଫରମାନ୍ସ ପାଇଁ ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ବର୍ତ୍ତମାନ ନୁହେଁ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index d3f10c1..aca2a38 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s ਵੱਲੋਂ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ਬਿਹਤਰ ਨੈੱਟਵਰਕ ਕਾਰਗੁਜ਼ਾਰੀ ਲਈ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ਹੁਣੇ ਨਹੀਂ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pl/strings.xml b/packages/CarrierDefaultApp/res/values-pl/strings.xml
index d4e1c88..7f4a089 100644
--- a/packages/CarrierDefaultApp/res/values-pl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Kontynuuj mimo to w przeglądarce"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zwiększenie wydajności"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"Aplikacja %s zaleca wzmocnienie wydajności danych"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kup wzmocnienie wydajności i zyskaj lepszą wydajność sieci"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie teraz"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Zarządzaj"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kup wzmocnienie wydajności"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
index 17ffec7..a03c7c2 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomenda um aumento de performance"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compre um aumento de performance para ter uma melhor performance de rede"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
index de969d6..08148f1 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim através do navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento do desempenho"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomenda um aumento do desempenho"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compre um aumento do desempenho para melhorar o desempenho da rede"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerir"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Compre um aumento do desempenho."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
index 17ffec7..a03c7c2 100644
--- a/packages/CarrierDefaultApp/res/values-pt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomenda um aumento de performance"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Compre um aumento de performance para ter uma melhor performance de rede"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
index 0951864..6c59687 100644
--- a/packages/CarrierDefaultApp/res/values-ro/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Continuă oricum prin browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performanță"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s recomandă un boost de performanță"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Cumpără un boost de performanță pentru rețea"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nu acum"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionează"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Achiziționează un boost de performanță."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
index 1b16abe..a7cf01d 100644
--- a/packages/CarrierDefaultApp/res/values-ru/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Например, страница входа в аккаунт может быть фиктивной."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Продолжить в браузере"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Повышение производительности"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s рекомендует использовать повышение производительности"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Повысьте производительность сети за плату."</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сейчас"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Настроить"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Повысьте производительность сети за плату."</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index c4d4085..943d806 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"කෙසේ වුවත් බ්රවුසරය හරහා ඉදිරියට යන්න"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"කාර්ය සාධනය ඉහළ නැංවීම"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s කාර්ය සාධනය ඉහළ නැංවීමක් නිර්දේශ කරයි"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"වඩා හොඳ ජාල කාර්ය සාධනයක් සඳහා කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"දැන් නොවේ"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"කළමනාකරණය කරන්න"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
index ef889bd..950c789 100644
--- a/packages/CarrierDefaultApp/res/values-sk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Pokračovať pomocou prehliadača"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšenie výkonu"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s odporúča zvýšenie výkonu"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Kúpte si optimalizáciu pripojenia pre vyšší výkon"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teraz nie"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovať"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kúpte si zvýšenie výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sl/strings.xml b/packages/CarrierDefaultApp/res/values-sl/strings.xml
index 08f151a..8c72ac3 100644
--- a/packages/CarrierDefaultApp/res/values-sl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vseeno nadaljuj v brskalniku"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ojačevalnik zmogljivosti"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s priporoča uporabo ojačevalnika zmogljivosti"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Nakup ojačevalnika zmogljivosti za boljše delovanje omrežja"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne zdaj"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljanje"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite ojačevalnik zmogljivosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 4ce2955..7029c86 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s rekomandon një përforcim të performancës"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Bli një paketë përforcimi të performancës për një performancë më të mirë të rrjetit"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
index 937f9bf..990b531 100644
--- a/packages/CarrierDefaultApp/res/values-sr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Ипак настави преко прегледача"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Побољшање учинка"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s препоручује побољшање учинка"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Купите побољшање учинка за мрежу"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сада"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управљај"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Купите побољшање учинка."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sv/strings.xml b/packages/CarrierDefaultApp/res/values-sv/strings.xml
index 595c9b8..1eac728 100644
--- a/packages/CarrierDefaultApp/res/values-sv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sv/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Fortsätt ändå via webbläsaren"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestandahöjning"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s rekommenderar en prestandahöjning"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Köp en prestandahöjning och få bättre nätverksprestanda"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Inte nu"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Hantera"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Köp en prestandahöjning."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
index 9bcc0361..b6c5d96 100644
--- a/packages/CarrierDefaultApp/res/values-sw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Endelea hata hivyo kupitia kivinjari"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Kuongeza utendaji"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s inapendekeza uongeze utendaji"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Nunua programu ya kuongeza utendaji kwa ajili ya utendaji mzuri wa mtandao"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Si sasa"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Dhibiti"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Nunua programu ya kuongeza utendaji."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index 0c4cae3..7c24542 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"பரவாயில்லை, உலாவி வழியாகத் தொடர்க"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"பெர்ஃபார்மென்ஸ் பூஸ்ட்"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பரிந்துரைக்கிறது"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"சிறந்த நெட்வொர்க் செயல்திறனுக்குப் பெர்ஃபார்மென்ஸ் பூஸ்ட்டை வாங்குங்கள்"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"இப்போது வேண்டாம்"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"நிர்வகியுங்கள்"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ஒரு பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பர்ச்சேஸ் செய்யுங்கள்."</string>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
index 6d1d445..d1c3086 100644
--- a/packages/CarrierDefaultApp/res/values-te/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించండి"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"పనితీరు బూస్ట్"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"పనితీరు బూస్ట్ను %s సిఫార్సు చేస్తోంది"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"మెరుగైన నెట్వర్క్ పనితీరు కోసం పనితీరు బూస్ట్ను కొనుగోలు చేయండి"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ఇప్పుడు కాదు"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"మేనేజ్ చేయండి"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"పనితీరు బూస్ట్ను కొనుగోలు చేయండి."</string>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
index 9128b14..1b5749c 100644
--- a/packages/CarrierDefaultApp/res/values-th/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"การเพิ่มประสิทธิภาพ"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s แนะนำให้เพิ่มประสิทธิภาพ"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"ซื้อการเพิ่มประสิทธิภาพเพื่อให้เครือข่ายทำงานได้ดียิ่งขึ้น"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ไว้ทีหลัง"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"จัดการ"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"ซื้อการเพิ่มประสิทธิภาพ"</string>
diff --git a/packages/CarrierDefaultApp/res/values-tl/strings.xml b/packages/CarrierDefaultApp/res/values-tl/strings.xml
index d586463..6543c68 100644
--- a/packages/CarrierDefaultApp/res/values-tl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tl/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Halimbawa, maaaring hindi pag-aari ng ipinapakitang organisasyon ang page ng login."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pag-boost ng performance"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"Inirerekomenda ng %s ang pag-boost ng performance"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Bumili ng pang-boost ng performance para sa mas mahusay na performance ng network"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Huwag muna"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pamahalaan"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Bumili ng pang-boost ng performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-tr/strings.xml b/packages/CarrierDefaultApp/res/values-tr/strings.xml
index 0a9ebca..8484fdd 100644
--- a/packages/CarrierDefaultApp/res/values-tr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tr/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Yine de tarayıcıyla devam et"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artışı"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s performans artışı öneriyor"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Daha iyi ağ performansı için performans artışı satın alın"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Şimdi değil"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Yönet"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artışı satın alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-uk/strings.xml b/packages/CarrierDefaultApp/res/values-uk/strings.xml
index db7ae41..5e553b4 100644
--- a/packages/CarrierDefaultApp/res/values-uk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uk/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Наприклад, сторінка входу може не належати вказаній організації."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Усе одно продовжити у веб-переглядачі"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Підвищення продуктивності"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s рекомендує придбати підвищення продуктивності"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Придбайте підвищення продуктивності, щоб покращити якість роботи мережі"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не зараз"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Керувати"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Придбайте підвищення продуктивності."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 026e89c..e878156 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -15,10 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for performance_boost_notification_title (5017421773334474875) -->
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
<skip />
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"بہتر نیٹ ورک کی کارکردگی کے لیے پرفارمینس بوسٹ خریدیں"</string>
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
index 4ca4d3a..9c77538 100644
--- a/packages/CarrierDefaultApp/res/values-uz/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Brauzerda davom ettirish"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Unumdorlikni kuchaytirish"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s unumdorlikni kuchaytirish xizmatini tavsiya qiladi"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Yaxshiroq tarmoq unumdorligi uchun unumdorlikni kuchaytirish xizmatini xarid qiling"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hozir emas"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Boshqarish"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Unumdorlikni kuchaytirish xizmatini xarid qiling."</string>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
index 80a75da..16a740e 100644
--- a/packages/CarrierDefaultApp/res/values-vi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Ví dụ: trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Vẫn tiếp tục qua trình duyệt"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"Tăng hiệu suất"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s đề xuất mua gói tăng hiệu suất"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Mua gói tăng hiệu suất để nâng cao hiệu suất mạng"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Để sau"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Quản lý"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Mua gói tăng hiệu suất."</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
index f95e247..48cc440 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登录页面可能并不属于页面上显示的单位。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍然通过浏览器继续操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"性能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"%s建议购买一份性能提升方案"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"购买一份性能提升方案以优化网络性能"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"以后再说"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"购买一份性能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
index 56f4979..d5ddc1a 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入頁面可能並不屬於所顯示的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升服務"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"「%s」建議購買效能提升服務"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"購買效能提升服務可提高網絡效能"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升服務。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index b77e912..d8a6262 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升方案"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"「%s」建議購買效能提升方案"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"購買效能提升方案可以提高網路效能"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
index dcc6d5d..5edadd6 100644
--- a/packages/CarrierDefaultApp/res/values-zu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -15,8 +15,10 @@
<string name="ssl_error_example" msgid="6188711843183058764">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
<string name="ssl_error_continue" msgid="1138548463994095584">"Qhubeka noma kunjalo ngesiphequluli"</string>
<string name="performance_boost_notification_channel" msgid="3475440855635538592">"I-boost yokusebenza"</string>
- <string name="performance_boost_notification_title" msgid="5017421773334474875">"I-%s incoma i-boost yokusebenza"</string>
- <string name="performance_boost_notification_detail" msgid="7216286153533321852">"Thenga i-boost yokusebenza ukuze uthole ukusebenza okungcono kwenethiwekhi"</string>
+ <!-- no translation found for performance_boost_notification_title (946857427149305992) -->
+ <skip />
+ <!-- no translation found for performance_boost_notification_detail (362407668982648351) -->
+ <skip />
<string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hhayi manje"</string>
<string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Phatha"</string>
<string name="slice_purchase_app_label" msgid="7170191659233241166">"Thenga i-boost yokusebenza."</string>
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index c2350a2..a8e5143 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Moenie toelaat nie"</string>
<string name="consent_back" msgid="2560683030046918882">"Terug"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Gee programme op <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> dieselfde toestemmings as op <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan mikrofoon-, kamera- en liggingtoegang insluit, asook ander sensitiewe toestemmings op <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Jy kan hierdie toestemmings enige tyd verander in jou Instellings op <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Dit kan <strong>Mikrofoon-</strong>, <strong>Kamera-</strong>, <strong>Liggingtoegang-</strong> en ander sensitiewe toestemmings op <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> insluit. <br/><br/>Jy kan hierdie toestemmings enige tyd in jou Instellings op <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> verander."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Program-ikoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Meer Inligting-knoppie"</string>
<string name="permission_phone" msgid="2661081078692784919">"Foon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakte"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofoon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Oproeprekords"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Toestelle in die omtrek"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
<string name="permission_notification" msgid="693762568127741203">"Kennisgewings"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Toestel in die Omtrek-stroming"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Kan foonoproepe maak en bestuur"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan foonoproeprekord lees en skryf"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Kan SMS-boodskappe stuur en ontvang"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kan by jou kontakte ingaan"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan by jou kalender ingaan"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Kan die mikrofoon gebruik om oudio op te neem"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan toestelle in die omtrek opspoor, aan hulle koppel en hul relatiewe posisie bepaal"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan alle kennisgewings lees, insluitend inligting soos kontakte, boodskappe en foto\'s"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Stroom jou foon se apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index f629c04f..f6abda8 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"አትፍቀድ"</string>
<string name="consent_back" msgid="2560683030046918882">"ተመለስ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"በ<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ላይ ላሉ መተግበሪያዎች በ<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ላይ ካሉት ጋር ተመሳሳይ ፈቃዶች ይሰጣቸው?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ይህ የማይክሮፎን፣ የካሜራ እና የአካባቢ መዳረሻ እና ሌሎች በ<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p> ላይ ያሉ አደገኛ ፈቃዶችን ሊያካትት ይችላል።እነዚህን ፈቃዶች በማንኛውም ጊዜ በ<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>ላይ ቅንብሮችዎ ውስጥ መቀየር ይችላሉ።"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ይህ <strong>ማይክሮፎን</strong>፣ <strong>ካሜራ</strong> እና <strong>የአካባቢ መዳረሻ</strong> እና ሌሎች አደገኛ ፈቃዶችን <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ላይ ሊያካትት ይችላል። <br/><br/>እነዚህን ቅንብሮች በማንኛውም ጊዜ ቅንብሮችዎ ውስጥ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ላይ መቀየር ይችላሉ።"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"የመተግበሪያ አዶ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"የተጨማሪ መረጃ አዝራር"</string>
<string name="permission_phone" msgid="2661081078692784919">"ስልክ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"ዕውቂያዎች"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ቀን መቁጠሪያ"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ማይክሮፎን"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"የጥሪ ምዝገባ ማስታወሻዎች"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"በአቅራቢያ ያሉ መሣሪያዎች"</string>
<string name="permission_storage" msgid="6831099350839392343">"ፎቶዎች እና ሚዲያ"</string>
<string name="permission_notification" msgid="693762568127741203">"ማሳወቂያዎች"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"መተግበሪያዎች"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"በአቅራቢያ ያለ መሣሪያ በዥረት መልቀቅ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"የስልክ ጥሪዎችን ማድረግ እና ማስተዳደር ይችላል"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"የስልክ ጥሪ ምዝገባ ማስታወሻን ማንበብ እና መጻፍ ይችላል"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"የኤስኤምኤስ መልዕክቶችን መላክ እና ማየት ይችላል"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ዕውቂያዎችዎን መድረስ ይችላል"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"የቀን መቁጠሪያዎን መድረስ ይችላል"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"ማይክሮፎኑን በመጠቀም ኦዲዮ መቅዳት ይችላል"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"በአቅራቢያ ያሉ መሣሪያዎችን ማግኘት፣ ከእነሱ ጋር መገናኘት እና አንጻራዊ ቦታቸውን መወሰን ይችላል"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"እንደ እውቂያዎች፣ መልዕክቶች እና ፎቶዎች ያሉ መረጃዎችን ጨምሮ ሁሉንም ማሳወቂያዎች ማንበብ ይችላል"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"የስልክዎን መተግበሪያዎች በዥረት ይልቀቁ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 4fe6140..013e1ec 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"عدم السماح"</string>
<string name="consent_back" msgid="2560683030046918882">"رجوع"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"هل تريد منح التطبيقات على <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> نفس الأذونات على <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>؟"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>قد تتضمَّن هذه الأذونات الوصول إلى الميكروفون والكاميرا والموقع الجغرافي وغيرها من أذونات الوصول إلى المعلومات الحسّاسة على <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>يمكنك تغيير هذه الأذونات في أي وقت في إعداداتك على <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"قد يتضمّن هذا الوصول إلى <strong>الميكروفون</strong> و<strong>الكاميرا</strong> و<strong>الموقع الجغرافي</strong> وأذونات الوصول إلى المعلومات الحساسة الأخرى في <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>يمكنك تغيير هذه الأذونات في أي وقت في إعداداتك على <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"رمز التطبيق"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"زر مزيد من المعلومات"</string>
<string name="permission_phone" msgid="2661081078692784919">"الهاتف"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"جهات الاتصال"</string>
<string name="permission_calendar" msgid="6805668388691290395">"التقويم"</string>
<string name="permission_microphone" msgid="2152206421428732949">"الميكروفون"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"سجلّ المكالمات"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"الأجهزة المجاورة"</string>
<string name="permission_storage" msgid="6831099350839392343">"الصور والوسائط"</string>
<string name="permission_notification" msgid="693762568127741203">"الإشعارات"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"التطبيقات"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"بثّ محتوى إلى الأجهزة المجاورة"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"يمكن إجراء المكالمات الهاتفية وإدارتها."</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"يمكن قراءة سجلّ المكالمات الهاتفية والكتابة فيه."</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"يمكن إرسال الرسائل القصيرة وعرضها."</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"يمكن الوصول إلى جهات الاتصال."</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"يمكن الوصول إلى التقويم."</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"يمكن تسجيل الصوت باستخدام الميكروفون."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"يمكن العثور على الموضع النسبي للأجهزة المجاورة والربط بها وتحديدها."</string>
<string name="permission_notification_summary" msgid="884075314530071011">"يمكن لهذا الملف الشخصي قراءة جميع الإشعارات، بما في ذلك المعلومات، مثل جهات الاتصال والرسائل والصور."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"بث تطبيقات هاتفك"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index 6938ed2..f2f0b1e 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"অনুমতি নিদিব"</string>
<string name="consent_back" msgid="2560683030046918882">"উভতি যাওক"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"এপ্সমূহক <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>ত দিয়াৰ দৰে <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>তো একে অনুমতি প্ৰদান কৰিবনে?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ইয়াত <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ত মাইক্ৰ’ফ’ন, কেমেৰা আৰু অৱস্থানৰ এক্সেছ আৰু অন্য সংবেদশীল অনুমতিসমূহ প্ৰদান কৰাটো অন্তৰ্ভুক্ত হ’ব পাৰে।</p> <p>আপুনি যিকোনো সময়তে <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ত থকা আপোনাৰ ছেটিঙত এই অনুমতিসমূহ সলনি কৰিব পাৰে।</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"এইটোত <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ৰ <strong>মাইক্ৰ’ফ’ন</strong>, <strong>কেমেৰা</strong>, আৰু <strong>অৱস্থানৰ এক্সেছ</strong>, আৰু অন্য সংবেদনশীল অনুমতিসমূহ অন্তৰ্ভুক্ত হ’ব পাৰে। <br/><br/>আপুনি যিকোনো সময়তে <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ত থকা আপোনাৰ ছেটিঙত এই অনুমতিসমূহ সলনি কৰিব পাৰে।"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"এপৰ চিহ্ন"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"অধিক তথ্যৰ বুটাম"</string>
<string name="permission_phone" msgid="2661081078692784919">"ফ’ন"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"সম্পৰ্ক"</string>
<string name="permission_calendar" msgid="6805668388691290395">"কেলেণ্ডাৰ"</string>
<string name="permission_microphone" msgid="2152206421428732949">"মাইক্ৰ’ফ’ন"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"কল লগ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"নিকটৱৰ্তী ডিভাইচ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ফট’ আৰু মিডিয়া"</string>
<string name="permission_notification" msgid="693762568127741203">"জাননী"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"এপ্"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"নিকটৱৰ্তী ডিভাইচত ষ্ট্ৰীম কৰা"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ফ’ন কল কৰিব আৰু পৰিচালনা কৰিব পাৰে"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ফ’নৰ কল লগ পঢ়িব আৰু লিখিব পাৰে"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"এছএমএছ বাৰ্তা পঠিয়াব আৰু চাব পাৰে"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"আপোনাৰ সম্পৰ্কসূচী এক্সেছ কৰিব পাৰে"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"আপোনাৰ কেলেণ্ডাৰ এক্সেছ কৰিব পাৰে"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"মাইক্ৰ’ফ’ন ব্যৱহাৰ কৰি অডিঅ’ ৰেকৰ্ড কৰিব পাৰে"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"নিকটৱৰ্তী ডিভাইচসমূহ বিচাৰিব, সেইসমূহৰ সৈতে সংযুক্ত হ’ব আৰু সেইসমূহৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"সম্পৰ্কসূচী, বাৰ্তা আৰু ফট’ৰ দৰে তথ্যকে ধৰি আটাইবোৰ জাননী পঢ়িব পাৰে"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"আপোনাৰ ফ’নৰ এপ্ ষ্ট্ৰীম কৰক"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 66b4916..454fa73 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"İcazə verməyin"</string>
<string name="consent_back" msgid="2560683030046918882">"Geriyə"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> cihazındakı tətbiqlərə <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> cihazındakılarla eyni icazələr verilsin?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Buraya <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındakı Mikrofon, Kamera və Məkana girişi və digər həssas icazələr daxil ola bilər.</p> <p>Bu icazələri istənilən vaxt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazında ayarlarınızda dəyişə bilərsiniz.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Buraya <strong>Mikrofon</strong>, <strong>Kamera</strong> və <strong>Məkana giriş</strong>, eləcə də <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazında digər həssas icazələr daxil ola bilər. Bu icazələri istənilən vaxt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazında ayarlarınızda dəyişə bilərsiniz.</p>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Tətbiq İkonası"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Ətraflı Məlumat Düyməsi"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakt"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Təqvim"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Zəng qeydləri"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Yaxınlıqdakı cihazlar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto və media"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirişlər"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Tətbiqlər"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Yaxınlıqdakı Cihazlarda Yayım"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon zəngi edə və onları idarə edə bilər"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefonun zəng qeydini oxuya və yaza bilər"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mesajları göndərə və baxa bilər"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktlarınıza giriş edə bilər"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Təqviminizə giriş edə bilər"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Mikrofonunuzdan istifadə edərək audio yaza bilər."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Yaxınlıqdakı cihazları tapa, qoşula və nisbi mövqeyi təyin edə bilər"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Bütün bildirişləri, o cümlədən kontaktlar, mesajlar və fotolar kimi məlumatları oxuya bilər"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun tətbiqlərini yayımlayın"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 09b8c0d..7734726 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ne dozvoli"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Aplikcijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> dajete sve dozvole kao na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može da obuhvata pristup mikrofonu, kameri i lokaciji, kao i drugim osetljivim dozvolama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>U svakom trenutku možete da promenite te dozvole u Podešavanjima na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"To može da obuhvata pristup <strong>mikrofonu</strong>, <strong>kameri</strong>, i <strong>lokaciji</strong>, i druge osetljive dozvole na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Možete da promenite te dozvole u bilo kom trenutku u Podešavanjima na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Dugme za više informacija"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Evidencije poziva"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Slike i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obaveštenja"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strimovanje, uređaji u blizini"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Može da upućuje telefonske pozive i upravlja njima"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može da čita i piše evidenciju poziva na telefonu"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Može da šalje i pregleda SMS poruke"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Može da pristupa kontaktima"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Može da pristupa kalendaru"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Može da snima zvuk pomoću mikrofona"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može da pronalazi i utvrđuje relativnu poziciju uređaja u blizini, kao i da se povezuje sa njima"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može da čita sva obaveštenja, uključujući informacije poput kontakata, poruka i slika"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Strimujte aplikacije na telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 2491298..0e60654 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Не дазваляць"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Даць праграмам на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> такія самыя дазволы, што і на прыладзе <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Дазволы могуць уключаць доступ да мікрафона, камеры і даных пра месцазнаходжанне, а таксама да іншай канфідэнцыяльнай інфармацыі на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можаце ў любы час змяніць гэтыя дазволы ў Наладах на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Праграмы змогуць атрымліваць доступ да <strong>мікрафона</strong>, <strong>камеры</strong> і <strong>даных пра месцазнаходжанне</strong>, а таксама да іншай канфідэнцыяльнай інфармацыі на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Вы можаце ў любы час змяніць гэтыя дазволы ў Наладах на прыладзе <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Значок праграмы"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Кнопка \"Даведацца больш\""</string>
<string name="permission_phone" msgid="2661081078692784919">"Тэлефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Кантакты"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Каляндар"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Мікрафон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Журналы выклікаў"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Прылады паблізу"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фота і медыяфайлы"</string>
<string name="permission_notification" msgid="693762568127741203">"Апавяшчэнні"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Праграмы"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Перадача плынню для прылады паблізу"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Можа рабіць тэлефонныя выклікі і кіраваць імі"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Можа счытваць і запісваць даныя ў журнале тэлефонных выклікаў"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Можа адпраўляць і праглядаць SMS-паведамленні"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Можа атрымліваць доступ да вашых кантактаў"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Можа атрымліваць доступ да вашага календара"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Можа запісваць аўдыя з выкарыстаннем мікрафона"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Можа знаходзіць прылады паблізу, падключацца да іх і вызначаць іх прыблізнае месцазнаходжанне"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Можа счытваць усе апавяшчэнні, уключаючы паведамленні, фота і інфармацыю пра кантакты"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляцыя змесціва праграм з вашага тэлефона"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index ce29de7..1db64e4 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Забраняване"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Искате ли да дадете на приложенията на <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> същите разрешения както на <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Това може да включва достъп до микрофона, камерата и местоположението, както и други разрешения за достъп до поверителна информация на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Можете да промените тези разрешения по всяко време от настройките на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Това може да включва достъп до <strong>микрофона</strong>, <strong>камерата</strong> и <strong>местоположението</strong>, както и други разрешения за достъп до поверителна информация на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Имате възможност да промените тези разрешения по всяко време от настройките на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона на приложението"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Бутон за още информация"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Списъци с обажданията"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства в близост"</string>
<string name="permission_storage" msgid="6831099350839392343">"Снимки и мултимедия"</string>
<string name="permission_notification" msgid="693762568127741203">"Известия"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Пот. предав. към у-ва наблизо"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Може да извършва и управлява телефонни обаждания"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чете списъка с телефонните обаждания и да записва в него"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Може да изпраща и преглежда SMS съобщения"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Може да осъществява достъп до контактите ви"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да осъществява достъп до календара ви"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Може да записва аудио посредством микрофона"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да намира и да се свързва с устройства в близост, както и да определя относителната им позиция"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Може да чете всички известия, включително различна информация, като например контакти, съобщения и снимки"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Поточно предаване на приложенията на телефона ви"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 02eae74..3013457 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"অনুমতি দেবেন না"</string>
<string name="consent_back" msgid="2560683030046918882">"ফিরুন"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>-এ যে অনুমতি দেওয়া আছে <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>-এও সেই একই অনুমতি দিতে চান?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>এটি <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>-এ হয়ত মাইক্রোফোন, ক্যামেরা এবং লোকেশনের অ্যাক্সেস ও অন্যান্য সংবেদনশীল অনুমতি অন্তর্ভুক্ত করতে পারে।</p> <p>আপনি যেকোনও সময় <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>-এর \'সেটিংস\' থেকে এইসব অনুমতি পরিবর্তন করতে পারবেন।</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"এর মধ্যে <strong>মাইক্রোফোন</strong>, <strong>ক্যামেরা</strong>, ও <strong>লোকেশন সংক্রান্ত অ্যাক্সেস </strong>, এবং <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.-এর অন্যান্য সংবেদনশীল অনুমতি অন্তর্ভুক্ত থাকতে পারে <br/><br/>আপনি যেকোনও সময়<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.-এর সেটিংস থেকে এইসব অনুমতি পরিবর্তন করতে পারবেন"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"অ্যাপের আইকন"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"আরও তথ্য সংক্রান্ত বোতাম"</string>
<string name="permission_phone" msgid="2661081078692784919">"ফোন"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"পরিচিতি"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ক্যালেন্ডার"</string>
<string name="permission_microphone" msgid="2152206421428732949">"মাইক্রোফোন"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"কল লগ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"আশেপাশের ডিভাইস"</string>
<string name="permission_storage" msgid="6831099350839392343">"ফটো ও মিডিয়া"</string>
<string name="permission_notification" msgid="693762568127741203">"বিজ্ঞপ্তি"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"অ্যাপ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"আশেপাশের ডিভাইসে স্ট্রিম করা"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ফোন কল করতে ও ম্যানেজ করতে পারবে"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ফোনের কল লগ পড়তে ও লিখতে পারবে"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"এসএমএস মেসেজ পাঠাতে ও দেখতে পারবে"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"আপনার পরিচিতি অ্যাক্সেস করতে পারবে"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"আপনার ক্যালেন্ডার অ্যাক্সেস করতে পারবে"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"মাইক্রোফোন ব্যবহার করে অডিও রেকর্ড করতে পারবেন"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"আশেপাশের ডিভাইস খুঁজে দেখতে, তার সাথে কানেক্ট করতে এবং তার আপেক্ষিক অবস্থান নির্ধারণ করতে পারবে"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"সব বিজ্ঞপ্তি পড়তে পারবে, যার মধ্যে পরিচিতি, মেসেজ ও ফটোর মতো তথ্য অন্তর্ভুক্ত"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"আপনার ফোনের অ্যাপ স্ট্রিম করুন"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 07daffb..f3829b0 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nemoj dozvoliti"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazad"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dati aplikacijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ista odobrenja kao na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ovo može uključivati pristup mikrofonu, kameri i lokaciji i druga osjetljiva odobrenja na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Uvijek možete promijeniti ova odobrenja u Postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ovo može uključivati odobrenja za pristup <strong>mikrofonu</strong>, <strong>kameri</strong> i <strong>lokaciji</strong> te druga osjetljiva odobrenja na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ova odobrenja možete bilo kada promijeniti u Postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Dugme Više informacija"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obavještenja"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Prijenos na uređajima u blizini"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Može uspostavljati telefonske pozive i upravljati njima"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može čitati i zapisivati zapisnik telefonskih poziva"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Može slati i prikazivati SMS poruke"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Može pristupiti kontaktima"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Može pristupiti kalendaru"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Može snimati zvuk pomoću mikrofona"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može pronaći uređaje u blizini, povezati se s njima i odrediti im relativan položaj"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sva obavještenja, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Prenosite aplikacije s telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index d03fca5..0e0919c 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"No permetis"</string>
<string name="consent_back" msgid="2560683030046918882">"Enrere"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vols concedir a les aplicacions del dispositiu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> els mateixos permisos que tenen a <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Això pot incloure accés al micròfon, a la càmera i a la ubicació, i altres permisos sensibles de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pots canviar aquests permisos en qualsevol moment a la configuració de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Això pot incloure l\'accés al <strong>micròfon</strong>, a la <strong>càmera</strong> i a la <strong>ubicació</strong>, així com altres permisos sensibles a <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Pots canviar aquestes permisos en qualsevol moment a Configuració, a <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona de l\'aplicació"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botó Més informació"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telèfon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contactes"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendari"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micròfon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registres de trucades"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositius propers"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos i contingut multimèdia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificacions"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacions"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Reproducció en disp. propers"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Pot fer i gestionar trucades"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pot llegir i escriure el registre de trucades del telèfon"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Pot enviar i consultar missatges SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pot accedir als contactes"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pot accedir al calendari"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Pots gravar àudios amb el micròfon"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pot determinar la posició relativa dels dispositius propers, cercar-los i connectar-s\'hi"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pot llegir totes les notificacions, inclosa informació com ara els contactes, els missatges i les fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Reprodueix en continu aplicacions del telèfon"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index ecfbac3..6f1bad7 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nepovolovat"</string>
<string name="consent_back" msgid="2560683030046918882">"Zpět"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Udělit aplikacím v zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> stejné oprávnění, jako mají v zařízení <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Může být zahrnut přístup k mikrofonu, fotoaparátu a poloze a další citlivá oprávnění na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tato oprávnění můžete v Nastavení na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> kdykoliv změnit.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"To může zahrnovat oprávnění <strong>Mikrofon</strong>, <strong>Fotoparát</strong> a <strong>Přístup k poloze</strong> a další citlivá oprávnění na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Tato oprávnění můžete kdykoli změnit v Nastavení na zařízení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikace"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tlačítko Další informace"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendář"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Seznamy hovorů"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Zařízení v okolí"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotky a média"</string>
<string name="permission_notification" msgid="693762568127741203">"Oznámení"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikace"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamování do zařízení v okolí"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Může uskutečňovat a spravovat telefonní hovory"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Může číst seznam telefonních hovorů a zapisovat do něj"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Může odesílat a číst zprávy SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Má přístup k vašim kontaktům"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Má přístup k vašemu kalendáři"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Může nahrávat zvuk pomocí mikrofonu"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Může nacházet zařízení v okolí, připojovat se k nim a zjišťovat jejich relativní polohu"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Může číst veškerá oznámení včetně informací, jako jsou kontakty, zprávy a fotky"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamujte aplikace v telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index 62a05d1..2b6c42b 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Tillad ikke"</string>
<string name="consent_back" msgid="2560683030046918882">"Tilbage"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vil du give apps på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> de samme tilladelser som på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan omfatte mikrofon-, kamera- og lokationsadgang samt andre tilladelser til at tilgå følsomme oplysninger på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan til enhver tid ændre disse tilladelser under Indstillinger på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Dette kan omfatte <strong>mikrofon-</strong>, <strong>kamera-</strong> og <strong>lokationsadgang</strong> samt andre tilladelser til at tilgå følsomme oplysninger på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Du kan til enhver tid ændre disse tilladelser under Indstillinger på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knappen Flere oplysninger"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Opkaldshistorik"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Enheder i nærheden"</string>
<string name="permission_storage" msgid="6831099350839392343">"Billeder og medier"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifikationer"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming til enhed i nærheden"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Kan foretage og administrere telefonopkald"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan læse og redigere opkaldshistorik"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sende og se sms-beskeder"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kan tilgå dine kontakter"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan tilgå din kalender"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Kan optage lyd via mikrofonen"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan finde, oprette forbindelse til og fastslå den omtrentlige lokation af enheder i nærheden"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan læse alle notifikationer, herunder oplysninger som f.eks. kontakter, beskeder og billeder"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream din telefons apps"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index 79d4df3..32873c0 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nicht zulassen"</string>
<string name="consent_back" msgid="2560683030046918882">"Zurück"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Apps auf <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> die gleichen Berechtigungen geben wie auf <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dazu können Berechtigungen für Mikrofon, Kamera und Standortzugriff sowie andere vertrauliche Berechtigungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gehören.</p><p>Sie lassen sich jederzeit in den Einstellungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ändern.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Dazu können <strong>Mikrofon</strong>, <strong>Kamera</strong> und <strong>Standortzugriff</strong> sowie weitere vertrauliche Berechtigungen auf <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gehören. <br/><br/>Du kannst diese Berechtigungen jederzeit in den Einstellungen von <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ändern."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App-Symbol"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Weitere-Infos-Schaltfläche"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakte"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Anrufliste"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Geräte in der Nähe"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos und Medien"</string>
<string name="permission_notification" msgid="693762568127741203">"Benachrichtigungen"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamen an Geräte in der Nähe"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Kann Anrufe tätigen und verwalten"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kann auf die Anrufliste zugreifen und sie bearbeiten"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Kann SMS senden und abrufen"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kann auf deine Kontakte zugreifen"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Kann auf deinen Kalender zugreifen"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Mit dem Mikrofon dürfen Audioaufnahmen gemacht werden"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kann Geräte in der Nähe finden, eine Verbindung zu ihnen herstellen und ihren relativen Standort ermitteln"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kann alle Benachrichtigungen lesen, einschließlich Informationen wie Kontakten, Nachrichten und Fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Smartphone-Apps streamen"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index a857b9a..5567f3a 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Να μην επιτρέπεται"</string>
<string name="consent_back" msgid="2560683030046918882">"Πίσω"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Παραχώρηση των ίδιων αδειών στις εφαρμογές στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> όπως στη συσκευή <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>;"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Αυτές μπορεί να περιλαμβάνουν πρόσβαση σε μικρόφωνο, κάμερα και τοποθεσία και άλλες άδειες πρόσβασης σε ευαίσθητες πληροφορίες στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Μπορείτε να αλλάξετε αυτές τις άδειες ανά πάσα στιγμή στις Ρυθμίσεις σας στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Μπορεί να περιλαμβάνει την πρόσβαση στο <strong>Μικρόφωνο</strong>, την <strong>Κάμερα</strong>, και την <strong>Τοποθεσία</strong>, καθώς και άλλες άδειες πρόσβασης σε ευαίσθητες πληροφορίες στη συσκευή <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Μπορείτε να αλλάξετε αυτές τις άδειες ανά πάσα στιγμή από τις Ρυθμίσεις της συσκευής <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Εικονίδιο εφαρμογής"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Κουμπί περισσότερων πληροφορ."</string>
<string name="permission_phone" msgid="2661081078692784919">"Τηλέφωνο"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Επαφές"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Ημερολόγιο"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Μικρόφωνο"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Αρχεία καταγραφής κλήσεων"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Συσκευές σε κοντινή απόσταση"</string>
<string name="permission_storage" msgid="6831099350839392343">"Φωτογραφίες και μέσα"</string>
<string name="permission_notification" msgid="693762568127741203">"Ειδοποιήσεις"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Εφαρμογές"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ροή σε κοντινή συσκευή"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Μπορεί να πραγματοποιήσει και να διαχειριστεί τηλεφωνικές κλήσεις"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Έχει άδεια ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων του τηλεφώνου"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Μπορεί να στείλει και να προβάλλει μηνύματα SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Έχει πρόσβαση στις επαφές σας"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Έχει πρόσβαση στο ημερολόγιό σας"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Μπορεί να εγγράφει ήχο χρησιμοποιώντας το μικρόφωνο"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Δεν μπορεί να βρει, να συνδεθεί και να προσδιορίσει τη σχετική τοποθεσία των κοντινών συσκευών"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Μπορεί να διαβάσει όλες τις ειδοποιήσεις, συμπεριλαμβανομένων πληροφοριών όπως επαφές, μηνύματα και φωτογραφίες"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Μεταδώστε σε ροή τις εφαρμογές του τηλεφώνου σας"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index ed63728..897f343 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
<string name="consent_back" msgid="2560683030046918882">"Back"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"This may include <strong>Microphone</strong>, <strong>Camera</strong>, and <strong>Location access</strong>, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index aeaef38..9905f28 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Don’t allow"</string>
<string name="consent_back" msgid="2560683030046918882">"Back"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"This may include <strong>Microphone</strong>, <strong>Camera</strong>, and <strong>Location access</strong>, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App Icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More Information Button"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index ed63728..897f343 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
<string name="consent_back" msgid="2560683030046918882">"Back"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"This may include <strong>Microphone</strong>, <strong>Camera</strong>, and <strong>Location access</strong>, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index ed63728..897f343 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Don\'t allow"</string>
<string name="consent_back" msgid="2560683030046918882">"Back"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include microphone, camera and location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions at any time in your settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"This may include <strong>Microphone</strong>, <strong>Camera</strong>, and <strong>Location access</strong>, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More information button"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index 25dd7ba..073aeca 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Don’t allow"</string>
<string name="consent_back" msgid="2560683030046918882">"Back"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Give apps on <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the same permissions as on <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>This may include Microphone, Camera, and Location access, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"This may include <strong>Microphone</strong>, <strong>Camera</strong>, and <strong>Location access</strong>, and other sensitive permissions on <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>You can change these permissions any time in your Settings on <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App Icon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"More Information Button"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 75c58b8..804c80b 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"¿Dar a las apps de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> los mismos permisos que tienen en <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir el acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos en cualquier momento en la Configuración del dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Esto puede incluir <strong>Micrófono</strong>, <strong>Cámara</strong>, y <strong>Acceso a la ubicación</strong>, así como otros permisos sensibles en <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Puedes cambiar estos permisos en cualquier momento desde la Configuración de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícono de la app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón Más información"</string>
<string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos y contenido multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Transmisión a disp. cercanos"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Puede hacer y administrar llamadas telefónicas"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puede leer y escribir el registro de llamadas telefónicas"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Puede enviar y ver mensajes SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Puede acceder a los contactos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Puede acceder al calendario"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Puede grabar audio con el micrófono"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puede encontrar, conectarse con y determinar la ubicación relativa de los dispositivos cercanos"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluso con información como contactos, mensajes y fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmitir las apps de tu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index b6676cb..5b25e15 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"No permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"¿Dar a las aplicaciones de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> los mismos permisos que <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Esto puede incluir acceso al micrófono, la cámara y la ubicación, así como otros permisos sensibles de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puedes cambiar estos permisos cuando quieras en los ajustes de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Esta acción puede dar acceso al <strong>micrófono</strong>, la <strong>cámara</strong> y la <strong>ubicación</strong>, así como a otros permisos sensibles en <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Puedes cambiar estos permisos cuando quieras en los ajustes de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icono de la aplicación"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón Más información"</string>
<string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registros de llamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos cercanos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos y elementos multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificaciones"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplicaciones"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming en dispositivos cercanos"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Puede hacer y gestionar llamadas"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puede leer y escribir en el registro de llamadas del teléfono"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Puede enviar y ver mensajes SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Puede acceder a tus contactos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Puede acceder a tu calendario"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Puede grabar audio usando el micrófono"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puede buscar, conectarse y determinar la posición relativa de dispositivos cercanos"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puede leer todas las notificaciones, incluida información como contactos, mensajes y fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Muestra en streaming las aplicaciones de tu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index f67c9a6..ed7507b 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ära luba"</string>
<string name="consent_back" msgid="2560683030046918882">"Tagasi"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Kas anda rakendustele seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> samad load, mis seadmes <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>See võib hõlmata mikrofoni, kaamerat ja juurdepääsu asukohale ning muid tundlikke lube seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Võite neid lube seadme <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> seadetes igal ajal muuta.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"See võib hõlmata <strong>mikrofoni</strong>, <strong>kaamerat</strong> ja <strong>juurdepääsu asukohale</strong> ning muid tundlikke lube seadmes <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Võite neid lube seadme <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> seadetes igal ajal muuta."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Rakenduse ikoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Nupp Lisateave"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktid"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Kõnelogid"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Läheduses olevad seadmed"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotod ja meedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Märguanded"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Rakendused"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Läheduses olevas seadmes esit."</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Saab teha ja hallata telefonikõnesid"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Saab telefoni kõnelogi lugeda ja sinna kirjutada"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Saab saata ja vaadata SMS-sõnumeid"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pääseb juurde teie kontaktidele"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pääseb juurde teie kalendrile"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Saab mikrofoni abil heli salvestada"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Leiab läheduses olevaid seadmeid, saab nendega ühenduse luua ja määrata nende suhtelise asendi"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kõikide märguannete, sealhulgas teabe, nagu kontaktid, sõnumid ja fotod, lugemine"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefoni rakenduste voogesitamine"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 98eec25..4b71149 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ez eman baimenik"</string>
<string name="consent_back" msgid="2560683030046918882">"Atzera"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> gailuan dituzten baimen berberak eman nahi dizkiezu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> gailuko aplikazioei?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Haien artean, baliteke <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gailuaren mikrofonoa, kamera, kokapena eta beste erabiltzeko kontuzko baimen batzuk egotea.</p> <p>Baimen horiek aldatzeko, joan <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> gailuaren ezarpenetara.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Baliteke <strong>mikrofonoa</strong>, <strong>kamera</strong> eta <strong>kokapena</strong> erabiltzeko baimenak barne hartzea, baita kontuzko informazioa erabiltzeko <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> gailuko beste baimen batzuk ere. <br/><br/>Baimen horiek aldatzeko, joan <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> gailuaren ezarpenetara."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Aplikazioaren ikonoa"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Informazio gehiagorako botoia"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefonoa"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktuak"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Egutegia"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofonoa erabiltzeko baimena"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Deien erregistroak"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Inguruko gailuak"</string>
<string name="permission_storage" msgid="6831099350839392343">"Argazkiak eta multimedia-edukia"</string>
<string name="permission_notification" msgid="693762568127741203">"Jakinarazpenak"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikazioak"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Inguruko gailuetara igortzeko baimena"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Telefono-deiak egin eta kudea ditzake"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefonoko deien erregistroa irakurri, eta bertan idatz dezake"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mezuak bidali eta ikus ditzake"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktuak atzi ditzake"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Egutegia atzi dezake"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Audioa graba dezake mikrofonoa erabilita"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Inguruko gailuak aurki ditzake, haietara konekta daiteke eta haien posizio erlatiboa zehatz dezake"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Jakinarazpen guztiak irakur ditzake; besteak beste, kontaktuak, mezuak, argazkiak eta antzeko informazioa"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Igorri zuzenean telefonoko aplikazioak"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 5fd7876..101353e 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"اجازه ندادن"</string>
<string name="consent_back" msgid="2560683030046918882">"برگشتن"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"به برنامههای موجود در <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> همان اجازههای <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> داده شود؟"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>این اجازهها میتواند شامل دسترسی به «میکروفون»، «دوربین»، و «مکان»، و دیگر اجازههای حساس در <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> شود.</p> <p>هروقت بخواهید میتوانید این اجازهها را در «تنظیمات» در <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> تغییر دهید.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"این مورد ممکن است شامل دسترسی به <strong>میکروفون</strong>، <strong>دوربین</strong>، و <strong>مکان</strong>، و دیگر اجازههای حساس در <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> شود. <br/><br/>هر زمان خواستید میتوانید این اجازهها را در «تنظیمات» <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> تغییر دهید."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"نماد برنامه"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"دکمه اطلاعات بیشتر"</string>
<string name="permission_phone" msgid="2661081078692784919">"تلفن"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"مخاطبین"</string>
<string name="permission_calendar" msgid="6805668388691290395">"تقویم"</string>
<string name="permission_microphone" msgid="2152206421428732949">"میکروفون"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"گزارشهای تماس"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"دستگاههای اطراف"</string>
<string name="permission_storage" msgid="6831099350839392343">"عکسها و رسانهها"</string>
<string name="permission_notification" msgid="693762568127741203">"اعلانها"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"برنامهها"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"جاریسازی دستگاههای اطراف"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"میتواند تماس تلفنی برقرار کند و این تماسها را مدیریت کند"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"میتواند گزارش تماسهای تلفنی را بنویسد و بخواند"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"میتواند پیامک ارسال کند و متن پیامک را مشاهده کند"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"میتواند به مخاطبین شما دسترسی داشته باشد"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"میتواند به تقویم شما دسترسی داشته باشد"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"میتواند بااستفاده از میکروفون صدا ضبط کند"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"میتواند دستگاههای اطراف را پیدا کند، به آنها متصل شود، و موقعیت نسبی آنها را تعیین کند"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"میتواند همه اعلانها، ازجمله اطلاعاتی مثل مخاطبین، پیامها، و عکسها را بخواند"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"جاریسازی برنامههای تلفن"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index 11e7c70..e92cabb 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Älä salli"</string>
<string name="consent_back" msgid="2560683030046918882">"Takaisin"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Anna laitteen <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> sovelluksille samat luvat kuin laitteella <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tähän voi kuulua pääsy mikrofoniin, kameraan ja sijaintiin sekä muita arkaluontoisia lupia laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Voit muuttaa lupia asetuksista milloin tahansa laitteella <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Tähän voi kuulua pääsy <strong>mikrofoniin</strong>, <strong>kameraan</strong>, ja <strong>sijaintiin </strong>, ja muihin arkaluontoisiin lupiin laitteella<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Voit muuttaa lupia milloin tahansa laitteen <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> asetuksissa."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Sovelluskuvake"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Lisätietopainike"</string>
<string name="permission_phone" msgid="2661081078692784919">"Puhelin"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Yhteystiedot"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalenteri"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofoni"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Puhelulokit"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Lähellä olevat laitteet"</string>
<string name="permission_storage" msgid="6831099350839392343">"Kuvat ja media"</string>
<string name="permission_notification" msgid="693762568127741203">"Ilmoitukset"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Sovellukset"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Striimaus muille laitteille"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Voi soittaa ja hallinnoida puheluita"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Voi lukea puhelulokia ja kirjoittaa siihen"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Voi lähettää ja nähdä tekstiviestejä"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Voi nähdä yhteystietosi"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Voi nähdä kalenterisi"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Voi tallentaa audiota mikrofonilla"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Voi löytää lähellä olevia laitteita, muodostaa niihin yhteyden ja määrittää niiden suhteellisen sijainnin"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Voi lukea kaikkia ilmoituksia, esim. kontakteihin, viesteihin ja kuviin liittyviä tietoja"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Striimaa puhelimen sovelluksia"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index 4059416..6e3df3e 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
<string name="consent_back" msgid="2560683030046918882">"Retour"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Accorder aux applications sur <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> les autorisations déjà accordées sur <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Cela peut comprendre l\'accès au microphone, à l\'appareil photo et à la position, ainsi que d\'autres autorisations sensibles sur <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations en tout temps dans vos paramètres sur <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Cela peut inclure l\'accès <strong>au microphone</strong>, <strong>à l\'appareil photo</strong>, et <strong>à la position</strong>, ainsi que d\'autres autorisations sensibles sur <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Vous pouvez modifier ces autorisations à tout moment dans vos paramètres sur <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icône de l\'application"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Bouton En savoir plus"</string>
<string name="permission_phone" msgid="2661081078692784919">"Téléphone"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microphone"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Journaux d\'appels"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos et fichiers multimédias"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Applications"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Diffusion en cours à proximité"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Peut passer et gérer des appels téléphoniques"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Peut lire et écrire les journaux d\'appels téléphoniques"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Peut envoyer et voir les messages texte"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Peut accéder à vos contacts"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Peut accéder à votre agenda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Il est possible d\'enregistrer du contenu audio en utilisant le microphone"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Peut trouver et déterminer la position relative des appareils à proximité, et s\'y connecter"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris les renseignements tels que les contacts, les messages et les photos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffusez les applications de votre téléphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index 0b94d40..5a93dc4 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ne pas autoriser"</string>
<string name="consent_back" msgid="2560683030046918882">"Retour"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Accorder les mêmes autorisations aux applis sur <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> que sur <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Il peut s\'agir de l\'accès au micro, à l\'appareil photo et à la position, et d\'autres autorisations sensibles sur l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Vous pouvez modifier ces autorisations à tout moment dans les paramètres de l\'appareil <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ceci peut inclure l\'accès au <strong>micro</strong>, à l\'<strong>appareil photo</strong> et à la <strong>position</strong>, ainsi que d\'autres autorisations sensibles sur <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Vous pouvez modifier ces autorisations à tout moment dans vos paramètres sur <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icône d\'application"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Bouton Plus d\'informations"</string>
<string name="permission_phone" msgid="2661081078692784919">"Téléphone"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micro"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Journaux d\'appels"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Appareils à proximité"</string>
<string name="permission_storage" msgid="6831099350839392343">"Photos et contenus multimédias"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifications"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Applis"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming appareil à proximité"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Peut passer des appels téléphoniques et les gérer"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Peut consulter et modifier les journaux d\'appels du téléphone"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Peut envoyer et afficher des SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Peut accéder à vos contacts"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Peut accéder à votre agenda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Peut enregistrer de l\'audio à l\'aide du micro"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Peut trouver les appareils à proximité, s\'y connecter et déterminer leur position relative"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Peut lire toutes les notifications, y compris des informations comme les contacts, messages et photos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Diffuser en streaming les applis de votre téléphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index f18157c..25ce2ba 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Non permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Atrás"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Queres darlles ás aplicacións de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> os mesmos permisos que teñen as de <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Con esta acción podes conceder acceso ao micrófono, á cámara e á localización, así como outros permisos de acceso á información confidencial de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Podes cambiar estes permisos en calquera momento na configuración de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Con esta acción podes conceder acceso a <strong>Micrófono</strong>, <strong>Cámara</strong>, e <strong>Acceso á localización</strong>, así como outros permisos de acceso á información confidencial de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Podes cambiar estes permisos en calquera momento na configuración de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona de aplicación"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botón de máis información"</string>
<string name="permission_phone" msgid="2661081078692784919">"Teléfono"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micrófono"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Rexistros de chamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e contido multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificacións"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplicacións"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Emitir a dispositivos próximos"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Pode facer e xestionar chamadas"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e editar o rexistro de chamadas do teléfono"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e ver mensaxes SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acceder aos contactos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acceder ao calendario"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Pode gravar audio usando o micrófono"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode atopar dispositivos próximos, conectarse a eles e determinar a súa posición relativa"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificacións (que poden incluír información como contactos, mensaxes e fotos)"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Emite as aplicacións do teu teléfono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 0a62551..4cfea49 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"મંજૂરી આપશો નહીં"</string>
<string name="consent_back" msgid="2560683030046918882">"પાછળ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> પરની ઍપને <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> પર છે તે જ પરવાનગીઓ આપીએ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>આમાં <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> પરના માઇક્રોફોન, કૅમેરા અને લોકેશનના ઍક્સેસ તથા અન્ય સંવેદનશીલ માહિતીની પરવાનગીઓ શામેલ હોઈ શકે છે.</p> <p>તમે <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> પર તમારા સેટિંગમાં તમે કોઈપણ સમયે આ પરવાનગીઓને બદલી શકો છો.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"આમાં <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> પરના <strong>માઇક્રોફોન</strong>, <strong>કૅમેરા</strong> અને <strong>લોકેશનના ઍક્સેસ</strong> તથા અન્ય સંવેદનશીલ માહિતીની પરવાનગીઓ શામેલ હોઈ શકે છે. <br/><br/>તમે કોઈપણ સમયે <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g> પર તમારા સેટિંગમાં આ પરવાનગીઓમાં ફેરફાર કરી શકો છો</strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ઍપનું આઇકન"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"વધુ માહિતી માટેનું બટન"</string>
<string name="permission_phone" msgid="2661081078692784919">"ફોન"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"સંપર્કો"</string>
<string name="permission_calendar" msgid="6805668388691290395">"કૅલેન્ડર"</string>
<string name="permission_microphone" msgid="2152206421428732949">"માઇક્રોફોન"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"કૉલ લૉગ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"નજીકના ડિવાઇસ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ફોટા અને મીડિયા"</string>
<string name="permission_notification" msgid="693762568127741203">"નોટિફિકેશન"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ઍપ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"નજીકના ડિવાઇસ પર સ્ટ્રીમિંગ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ફોન કૉલ કરી શકે છે અને તેને મેનેજ કરી શકે છે"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ફોન કૉલ લૉગ વાંચી અને લખી શકે છે"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS મેસેજ મોકલી શકે છે અને જોઈ શકે છે"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"તમારા સંપર્કો ઍક્સેસ કરી શકે છે"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"તમારા કૅલેન્ડરનો ઍક્સેસ કરી શકે છે"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"માઇક્રોફોનનો ઉપયોગ કરીને ઑડિયો રેકોર્ડ કરી શકાય છે"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"નજીકના ડિવાઇસ શોધી શકે છે, તેમની સાથે કનેક્ટ કરી શકે છે અને તેમની સંબંધિત સ્થિતિ નિર્ધારિત કરી શકે છે"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"સંપર્કો, મેસેજ અને ફોટા જેવી માહિતી સહિતના બધા નોટિફિકેશન વાંચી શકે છે"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"તમારા ફોનની ઍપ સ્ટ્રીમ કરો"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 6d7f1b4..b9492cc 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"अनुमति न दें"</string>
<string name="consent_back" msgid="2560683030046918882">"वापस जाएं"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"क्या <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> पर ऐप्लिकेशन को वही अनुमतियां देनी हैं जो <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> पर दी हैं?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>इसमें <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> पर मौजूद माइक्रोफ़ोन, कैमरा, जगह की जानकारी को ऐक्सेस करने, और अन्य संवेदनशील जानकारी ऐक्सेस करने की अनुमतियां शामिल हो सकती हैं.</p> <p>किसी भी समय <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> की सेटिंग में जाकर, इन अनुमतियों में बदलाव किए जा सकते हैं.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"इसमें <strong>माइक्रोफ़ोन</strong>, <strong>कैमरा</strong>, <strong>जगह की जानकारी</strong>, के ऐक्सेस के साथ-साथ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> पर संवेदनशील जानकारी ऐक्सेस करने की अन्य अनुमतियां भी शामिल हो सकती हैं. <br/><br/>इन अनुमतियों को <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> में जाकर कभी-भी बदला जा सकता है."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ऐप्लिकेशन आइकॉन"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ज़्यादा जानकारी वाला बटन"</string>
<string name="permission_phone" msgid="2661081078692784919">"फ़ोन"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"संपर्क"</string>
<string name="permission_calendar" msgid="6805668388691290395">"कैलेंडर"</string>
<string name="permission_microphone" msgid="2152206421428732949">"माइक्रोफ़ोन"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"कॉल लॉग"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"आस-पास मौजूद डिवाइस"</string>
<string name="permission_storage" msgid="6831099350839392343">"फ़ोटो और मीडिया"</string>
<string name="permission_notification" msgid="693762568127741203">"सूचनाएं"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ऐप्लिकेशन"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"आस-पास के डिवाइस पर स्ट्रीमिंग"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"फ़ोन कॉल करने और उन्हें मैनेज करने की अनुमति है"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"कॉल लॉग देखने और उसमें बदलाव करने की अनुमति है"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"एसएमएस भेजने और उन्हें देखने की अनुमति है"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"आपकी संपर्क सूची को ऐक्सेस करने की अनुमति है"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"कैलेंडर को ऐक्सेस करने की अनुमति है"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"माइक्रोफ़ोन का इस्तेमाल करके ऑडियो रिकॉर्ड किया जा सकता है"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"आपको आस-पास मौजूद डिवाइसों को खोजने, उनसे कनेक्ट करने, और उनकी जगह की जानकारी का पता लगाने की अनुमति है"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"इससे सभी सूचनाएं देखी जा सकती हैं. इनमें संपर्क, मैसेज, और फ़ोटो जैसी जानकारी शामिल होती है"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"अपने फ़ोन पर मौजूद ऐप्लिकेशन स्ट्रीम करें"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 2210785..15e2b22 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nemoj dopustiti"</string>
<string name="consent_back" msgid="2560683030046918882">"Natrag"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dati jednaka dopuštenja aplikacijama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> kao i na uređaju <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To može uključivati pristup mikrofonu, kameri i lokaciji i druga dopuštenja za osjetljive podatke na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dopuštenja uvijek možete promijeniti u postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"To može uključivati <strong>pristup mikrofonu</strong>, <strong>kameri</strong> i <strong>lokaciji</strong> te druga dopuštenja za osjetljive podatke na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ta dopuštenja uvijek možete promijeniti u postavkama na uređaju <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Gumb Više informacija"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakti"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Zapisnici poziva"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Uređaji u blizini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije i mediji"</string>
<string name="permission_notification" msgid="693762568127741203">"Obavijesti"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamanje uređaja u blizini"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Može uspostavljati telefonske pozive i upravljati njima"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Može čitati i pisati zapisnik poziva telefona"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Može slati i pregledavati SMS poruke"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Može pristupiti vašim kontaktima"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Može pristupiti vašem kalendaru"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Može snimiti zvuk pomoću mikrofona"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Može pronaći i odrediti relativni položaj uređaja u blizini i povezati se s njima"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Može čitati sve obavijesti, uključujući informacije kao što su kontakti, poruke i fotografije"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikacija vašeg telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 6dec223..6a07011 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Tiltás"</string>
<string name="consent_back" msgid="2560683030046918882">"Vissza"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Ugyanolyan engedélyeket ad a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> eszközön található alkalmazásoknak, mint a(z) <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> eszköz esetén?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ide tartozhatnak a mikrofonhoz, a kamerához és a helyhez való hozzáférések, valamint a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> eszközön érvényes egyéb, bizalmas adatokra vonatkozó hozzáférési engedélyek is.</p> <p>Ezeket az engedélyeket bármikor módosíthatja a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> eszköz beállításai között.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ide tartozhat a <strong>mikrofonhoz</strong>, a <strong>kamerához</strong> és a <strong>helyadatokhoz</strong> való hozzáférés, valamint a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> eszközön érvényes egyéb bizalmas engedélyek is. <br/><br/>Ezeket az engedélyeket bármikor módosíthatja a(z) <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> eszköz beállításai között."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Alkalmazás ikonja"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"További információ gomb"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Címtár"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Naptár"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Hívásnaplók"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Közeli eszközök"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotók és médiatartalmak"</string>
<string name="permission_notification" msgid="693762568127741203">"Értesítések"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Alkalmazások"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamelés közeli eszközökre"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Hívásokat indíthat és kezelhet"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Olvashatja és írhatja a telefon hívásnaplóját"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS-üzeneteket küldhet és tekinthet meg"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Hozzáférhet a névjegyekhez"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Hozzáférhet a naptárhoz"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Hangfelvételt készíthet a mikrofon használatával."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Megkeresheti a közeli eszközöket, meghatározhatja viszonylagos helyzetüket és csatlakozhat hozzájuk"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Elolvashat minden értesítést, ideértve az olyan információkat, mint a névjegyek, az üzenetek és a fotók"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"A telefon alkalmazásainak streamelése"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index a890e93..4ff57bc 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Չթույլատրել"</string>
<string name="consent_back" msgid="2560683030046918882">"Հետ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>-ում հավելվածներին տա՞լ նույն թույլտվությունները, ինչ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>-ում"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Դրանք կարող են ներառել խոսափողի, տեսախցիկի և տեղադրության տվյալների օգտագործման թույլտվությունները, ինչպես նաև կոնֆիդենցիալ տեղեկությունների օգտագործման այլ թույլտվություններ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> սարքում։</p> <p>Այդ թույլտվությունները ցանկացած ժամանակ կարելի է փոխել <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> սարքի ձեր կարգավորումներում։</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Սա կարող է ներառել <strong>խոսափողի</strong>, <strong&gtտեսախցիկի</strong>, <strong>տեղադրության</strong> և այլ կոնֆիդենցիալ տվյալների օգտագործման թույլտվությունները <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> սարքում։ <br/><br/>Այդ թույլտվությունները ցանկացած ժամանակ կարող եք փոխել <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> սարքի ձեր կարգավորումներում։"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Հավելվածի պատկերակ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"«Այլ տեղեկություններ» կոճակ"</string>
<string name="permission_phone" msgid="2661081078692784919">"Հեռախոս"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Կոնտակտներ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Օրացույց"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Խոսափող"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Կանչերի ցուցակ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Մոտակա սարքեր"</string>
<string name="permission_storage" msgid="6831099350839392343">"Լուսանկարներ և մուլտիմեդիա"</string>
<string name="permission_notification" msgid="693762568127741203">"Ծանուցումներ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Հավելվածներ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Հեռարձակում մոտակա սարքերին"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Կարող է կատարել հեռախոսազանգեր և կառավարել դրանք"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Կարող է դիտել և գրանցել կանչերը"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Կարող է ուղարկել SMS հաղորդագրություններ և դիտել դրանք"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Կարող է օգտագործել ձեր կոնտակտները"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Կարող է օգտագործել ձեր օրացույցը"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Կարող է օգտագործել խոսափողը՝ ձայնագրություններ անելու համար"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Կարող է գտնել և որոշել մոտակա սարքերի մոտավոր դիրքը և միանալ դրանց"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Կարող է կարդալ բոլոր ծանուցումները, ներառյալ տեղեկությունները, օրինակ՝ կոնտակտները, հաղորդագրությունները և լուսանկարները"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Հեռարձակել հեռախոսի հավելվածները"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 153797a..39e288a 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Jangan izinkan"</string>
<string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Berikan aplikasi di <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> izin yang sama seperti di <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini termasuk akses Mikrofon, Kamera, dan Lokasi, serta izin sensitif lainnya di <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda dapat mengubah izin ini kapan saja di Setelan di <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ini bisa termasuk <strong>Mikrofon</strong>, <strong>Kamera</strong>, dan <strong>Akses lokasi</strong>, serta izin sensitif lainnya di <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Anda dapat mengubah izin ini kapan saja di Setelan <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikon Aplikasi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tombol Informasi Lainnya"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telepon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontak"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Log panggilan"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Perangkat di sekitar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifikasi"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikasi"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming Perangkat di Sekitar"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Dapat melakukan dan mengelola panggilan telepon"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Dapat membaca dan menulis log panggilan telepon"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Dapat mengirim dan melihat pesan SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Dapat mengakses kontak Anda"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Dapat mengakses kalender Anda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Dapat merekam audio menggunakan mikrofon"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Dapat menemukan, menghubungkan, dan menentukan posisi relatif dari perangkat di sekitar"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Dapat membaca semua notifikasi, termasuk informasi seperti kontak, pesan, dan foto"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streaming aplikasi ponsel"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 60ae27c..6ebe205 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -43,7 +43,8 @@
<string name="consent_no" msgid="2640796915611404382">"Ekki leyfa"</string>
<string name="consent_back" msgid="2560683030046918882">"Til baka"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Veita forritum í <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> sömu heimildir og í <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Þetta kann að fela í sér aðgang að hljóðnema, myndavél og staðsetningu og aðrar heimildir fyrir viðkvæmu efni í <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Hægt er að breyta þessum heimildum hvenær sem er í stillingunum í <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <!-- no translation found for permission_sync_summary (765497944331294275) -->
+ <skip />
<string name="vendor_icon_description" msgid="4445875290032225965">"Tákn forrits"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Hnappur fyrir upplýsingar"</string>
<string name="permission_phone" msgid="2661081078692784919">"Sími"</string>
@@ -51,26 +52,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Tengiliðir"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Dagatal"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Hljóðnemi"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Símtalaskrár"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Nálæg tæki"</string>
<string name="permission_storage" msgid="6831099350839392343">"Myndir og efni"</string>
<string name="permission_notification" msgid="693762568127741203">"Tilkynningar"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Forrit"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streymi í nálægum tækjum"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Getur hringt og stjórnað símtölum"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Getur lesið og skrifað símtalaskrá símans"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Getur sent og skoðað SMS-skilaboð"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Hefur aðgang að tengiliðum"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Hefur aðgang að dagatalinu"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Getur tekið upp hljóð með hljóðnemanum"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Getur fundið, tengst og áætlað staðsetningu nálægra tækja"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Getur lesið allar tilkynningar, þar á meðal upplýsingar á borð við tengiliði, skilaboð og myndir"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streymdu forritum símans"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 9f3c9cd..49b1fbd 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Non consentire"</string>
<string name="consent_back" msgid="2560683030046918882">"Indietro"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vuoi dare alle app su <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> le stesse autorizzazioni che hai dato su <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Potrebbero essere incluse le autorizzazioni di accesso al microfono, alla fotocamera e alla posizione, nonché altre autorizzazioni sensibili su <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puoi cambiare queste autorizzazioni in qualsiasi momento nelle Impostazioni su <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Potrebbero essere incluse le autorizzazioni <strong>Microfono</strong>, <strong>Fotocamera</strong> e <strong>Accesso alla posizione</strong>, oltre ad altre autorizzazioni sensibili su <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Puoi cambiare queste autorizzazioni in qualsiasi momento nelle Impostazioni su <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icona dell\'app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Pulsante Altre informazioni"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefono"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contatti"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendario"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfono"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registri chiamate"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivi nelle vicinanze"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto e contenuti multimediali"</string>
<string name="permission_notification" msgid="693762568127741203">"Notifiche"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"App"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming dispos. in vicinanze"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Consente di effettuare e gestire telefonate"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Consente di leggere e modificare il registro chiamate del telefono"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Consente di inviare e visualizzare SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Consente di accedere ai tuoi contatti"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Consente di accedere al tuo calendario"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Consente di registrare audio usando il microfono"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Consente di trovare e connettersi a dispositivi nelle vicinanze, nonché di stabilirne la posizione relativa"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Puoi leggere tutte le notifiche, incluse le informazioni come contatti, messaggi e foto"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Trasmetti in streaming le app del tuo telefono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index c435f67..167e216 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"אין אישור"</string>
<string name="consent_back" msgid="2560683030046918882">"חזרה"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"האם לתת לאפליקציות ב-<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>את אותן הרשאות כמו ב-<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ההרשאות עשויות לכלול גישה למיקרופון, למצלמה ולמיקום, וכן גישה למידע רגיש אחר ב-</strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p&gt; <p>אפשר לשנות את ההרשאות האלה בכל שלב בהגדרות של <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ההרשאות עשויות לכלול גישה ל<strong>מיקרופון</strong>, ל<strong>מצלמה</strong>, ול<strong>מיקום</strong>, וכן גישה למידע רגיש אחר ב-<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>אפשר לשנות את ההרשאות האלה בכל שלב בהגדרות של <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"סמל האפליקציה"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"לחצן מידע נוסף"</string>
<string name="permission_phone" msgid="2661081078692784919">"טלפון"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"אנשי קשר"</string>
<string name="permission_calendar" msgid="6805668388691290395">"יומן"</string>
<string name="permission_microphone" msgid="2152206421428732949">"מיקרופון"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"יומני שיחות"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"מכשירים בקרבת מקום"</string>
<string name="permission_storage" msgid="6831099350839392343">"תמונות ומדיה"</string>
<string name="permission_notification" msgid="693762568127741203">"התראות"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"אפליקציות"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"סטרימינג למכשירים בקרבת מקום"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"אפשרות לבצע ולנהל שיחות טלפון"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"אפשרות ולקרוא ולכתוב נתונים ביומן השיחות של הטלפון"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"אפשרות לשלוח הודעות SMS ולצפות בהן"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"גישה לאנשי הקשר"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"אפשרות לגשת ליומן"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"הרשאה להשתמש במיקרופון כדי להקליט אודיו"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"אפשרות למצוא מכשירים בקרבת מקום, להתחבר אליהם ולהעריך את המיקום היחסי שלהם"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"גישת קריאה לכל ההתראות, כולל מידע כמו אנשי קשר, הודעות ותמונות."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"שידור אפליקציות מהטלפון"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index cfd21a9..599bffa 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"許可しない"</string>
<string name="consent_back" msgid="2560683030046918882">"戻る"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> のアプリに <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> の場合と同じ権限を付与しますか?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>これには、<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> のマイク、カメラ、位置情報へのアクセスや、その他の機密情報に関わる権限が含まれる可能性があります。</p> <p>これらの権限は <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> の [設定] でいつでも変更できます。</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"これには、<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> の<strong>マイク</strong>、<strong>カメラ</strong>、<strong>位置情報へのアクセス</strong>や、その他の機密情報に関わる権限が含まれる可能性があります。<br/><br/>これらの権限は <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> の [設定] でいつでも変更できます。"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"アプリのアイコン"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"詳細情報ボタン"</string>
<string name="permission_phone" msgid="2661081078692784919">"電話"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"連絡先"</string>
<string name="permission_calendar" msgid="6805668388691290395">"カレンダー"</string>
<string name="permission_microphone" msgid="2152206421428732949">"マイク"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"通話履歴"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"付近のデバイス"</string>
<string name="permission_storage" msgid="6831099350839392343">"写真とメディア"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"アプリ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"付近のデバイスへのストリーミング"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"電話の発信と管理を行えます"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"通話履歴の読み取りと書き込みを行えます"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS メッセージの送信、表示を行えます"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"連絡先にアクセスできます"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"カレンダーにアクセスできます"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"マイクを使って録音できます"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"付近のデバイスの検出、接続、相対位置の特定を行えます"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"連絡先、メッセージ、写真に関する情報を含め、すべての通知を読み取ることができます"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"スマートフォンのアプリをストリーミングします"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 4f8b103..0f578ea 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"არ დაიშვას"</string>
<string name="consent_back" msgid="2560683030046918882">"უკან"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"გსურთ აპებს <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>-ზე იგივე ნებართვები მიანიჭოთ, როგორიც აქვს <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>-ზე?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>აღნიშნული შეიძლება მოიცავდეს მიკროფონზე, კამერასა და მდებარეობაზე წვდომას თუ სხვა ნებართვას სენსიტიურ ინფორმაციაზე <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>-ში.</p> <p>ამ ნებართვების შეცვლა ნებისმიერ დროს შეგიძლიათ თქვენი პარამეტრებიდან <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>-ში.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ეს შესაძლოა მოიცავდეს შემდეგს: <strong>მიკროფონი</strong>, <strong>კამერა</strong> და <strong>მდებარეობაზე წვდომა</strong> და <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>-ის სხვა ნებართვა სენსიტიურ ინფორმაციაზე. <br/><br/>ამ ნებართვების შეცვლა ნებისმიერ დროს შეგიძლიათ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>-ის პარამეტრებიდან."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"აპის ხატულა"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"დამატებითი ინფორმაციის ღილაკი"</string>
<string name="permission_phone" msgid="2661081078692784919">"Phone"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"კონტაქტები"</string>
<string name="permission_calendar" msgid="6805668388691290395">"კალენდარი"</string>
<string name="permission_microphone" msgid="2152206421428732949">"მიკროფონი"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ზარების ჟურნალები"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ახლომახლო მოწყობილობები"</string>
<string name="permission_storage" msgid="6831099350839392343">"ფოტოები და მედია"</string>
<string name="permission_notification" msgid="693762568127741203">"შეტყობინებები"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"აპები"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ახლომდებარე მოწყობილობის სტრიმინგი"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"შეძლოს სატელეფონო ზარების განხორციელება და მართვა"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"შეეძლოს ზარების ჟურნალის წაკითხვა და მასში ჩაწერა"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"შეძლოს SMS ტექსტური შეტყობინებების გაგზავნა და მიღება"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ჰქონდეს თქვენს კონტაქტებზე წვდომის საშუალება"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ჰქონდეს თქვენს კალენდარზე წვდომის საშუალება"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"შეუძლია აუდიოს ჩაწერა მიკროფონის გამოყენებით"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"შეძლოს ახლომახლო მოწყობილობების აღმოჩენა, მათთან დაკავშირება და მათი შედარებითი პოზიციის დადგენა"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"შეუძლია წაიკითხოს ყველა შეტყობინება, მათ შორის ისეთი ინფორმაცია, როგორიცაა კონტაქტები, ტექსტური შეტყობინებები და ფოტოები"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"თქვენი ტელეფონის აპების სტრიმინგი"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 70b3623..883269d 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Рұқсат бермеу"</string>
<string name="consent_back" msgid="2560683030046918882">"Артқа"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> құрылғысындағы қолданбаларға <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> құрылғысындағыдай рұқсаттар берілсін бе?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Оларға микрофонды, камераны және геодеректі пайдалану рұқсаттары, сондай-ақ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> құрылғысына берілетін басқа да құпия ақпарат рұқсаттары кіруі мүмкін.</p> <p>Бұл рұқсаттарды кез келген уақытта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> құрылғысындағы параметрлерден өзгерте аласыз.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Оған <strong>микрофонды</strong>, <strong>камераны</strong> және <strong>локацияны пайдалану рұқсаттары</strong>, сондай-ақ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> құрылғысындағы басқа да құпия ақпарат рұқсаттары кіруі мүмкін. <br/><br/>Бұл рұқсаттарды кез келген уақытта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> құрылғысындағы параметрлерден өзгертуіңізге болады."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Қолданба белгішесі"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"\"Қосымша ақпарат\" түймесі"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контактілер"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Күнтізбе"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Қоңырау журналдары"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Маңайдағы құрылғылар"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фотосуреттер мен медиафайлдар"</string>
<string name="permission_notification" msgid="693762568127741203">"Хабарландырулар"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Қолданбалар"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Маңайдағы құрылғыға трансляция"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Қоңырау шалып, оларды басқара алады."</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Телефонның қоңыраулар журналын оқып, жаза алады."</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS хабарларды көріп, жібере алады."</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Контактілеріңізді пайдалана алады."</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Күнтізбеңізді пайдалана алады."</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Микрофон пайдалану арқылы аудио жаза алады."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Маңайдағы құрылғыларды тауып, олармен байланысып, бір-біріне қатысты локациясын анықтайды."</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Барлық хабарландыруды, соның ішінде контактілер, хабарлар және фотосуреттер сияқты ақпаратты оқи алады."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефон қолданбаларын трансляциялайды."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 85c1806..e46c791 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"មិនអនុញ្ញាត"</string>
<string name="consent_back" msgid="2560683030046918882">"ថយក្រោយ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ផ្ដល់ការអនុញ្ញាតឱ្យកម្មវិធីនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ដូចនៅលើ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ឬ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>សកម្មភាពនេះអាចរួមបញ្ចូលការចូលប្រើទីតាំង កាមេរ៉ា និងមីក្រូហ្វូន និងការអនុញ្ញាតដែលមានលក្ខណៈរសើបផ្សេងទៀតនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>។</p> <p>អ្នកអាចប្ដូរការអនុញ្ញាតទាំងនេះបានគ្រប់ពេលវេលានៅក្នុងការកំណត់នៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>។</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"សកម្មភាពនេះអាចរួមបញ្ចូល<strong>មីក្រូហ្វូន</strong> <strong>កាមេរ៉ា</strong> និង<strong>សិទ្ធិចូលប្រើទីតាំង</strong> និងការអនុញ្ញាតដែលមានលក្ខណៈរសើបផ្សេងទៀតនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>។ <br/><br/>អ្នកអាចប្ដូរការអនុញ្ញាតទាំងនេះបានគ្រប់ពេលនៅក្នុងការកំណត់របស់អ្នកនៅលើ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>។"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"រូបកម្មវិធី"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ប៊ូតុងព័ត៌មានបន្ថែម"</string>
<string name="permission_phone" msgid="2661081078692784919">"ទូរសព្ទ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ប្រតិទិន"</string>
<string name="permission_microphone" msgid="2152206421428732949">"មីក្រូហ្វូន"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"កំណត់ហេតុហៅទូរសព្ទ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ឧបករណ៍នៅជិត"</string>
<string name="permission_storage" msgid="6831099350839392343">"រូបថត និងមេឌៀ"</string>
<string name="permission_notification" msgid="693762568127741203">"ការជូនដំណឹង"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"កម្មវិធី"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ការផ្សាយទៅឧបករណ៍នៅជិត"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"អាចហៅទូរសព្ទ និងគ្រប់គ្រងការហៅទូរសព្ទ"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"អាចអាន និងសរសេរកំណត់ហេតុហៅទូរសព្ទ"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"អាចផ្ញើ និងមើលសារ SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"អាចចូលប្រើទំនាក់ទំនងរបស់អ្នក"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"អាចចូលប្រើប្រតិទិនរបស់អ្នក"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"អាចថតសំឡេងដោយប្រើមីក្រូហ្វូន"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"អាចស្វែងរក ភ្ជាប់ទៅ និងកំណត់ចម្ងាយពាក់ព័ន្ធរវាងឧបករណ៍ដែលនៅជិត"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"អាចអានការជូនដំណឹងទាំងអស់ រួមទាំងព័ត៌មានដូចជាទំនាក់ទំនង សារ និងរូបថត"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ផ្សាយកម្មវិធីរបស់ទូរសព្ទអ្នក"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index ef4699c..c81a441 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ಅನುಮತಿಸಬೇಡಿ"</string>
<string name="consent_back" msgid="2560683030046918882">"ಹಿಂದೆ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"</strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ನಲ್ಲಿನ ಅನುಮತಿಗಳನ್ನೇ </strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ನಲ್ಲಿನ ಆ್ಯಪ್ಗಳಿಗೆ ನೀಡಬೇಕೆ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ಇದು <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ನಲ್ಲಿನ ಮೈಕ್ರೊಫೋನ್, ಕ್ಯಾಮರಾ ಮತ್ತು ಸ್ಥಳ ಆ್ಯಕ್ಸೆಸ್ ಹಾಗೂ ಇತರ ಸೂಕ್ಷ್ಮ ಅನುಮತಿಗಳನ್ನು ಹೊಂದಿರಬಹುದು<p></p> <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ನಲ್ಲಿನ ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ನೀವು ಈ ಅನುಮತಿಗಳನ್ನು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ಇದು <strong>ಮೈಕ್ರೋಫೋನ್</strong>, <strong>ಕ್ಯಾಮರಾ</strong>, and <strong>ಸ್ಥಳದ ಆ್ಯಕ್ಸೆಸ್</strong>, ಮತ್ತು <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ನಲ್ಲಿ ಸೂಕ್ಷ್ಮ ಮಾಹಿತಿಗಾಗಿ ಇತರ ಅನುಮತಿಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು. <br/><br/>ನೀವು <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ನಲ್ಲಿನ ನಿಮ್ಮ ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಈ ಅನುಮತಿಗಳನ್ನು ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ಆ್ಯಪ್ ಐಕಾನ್"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ಹೆಚ್ಚಿನ ಮಾಹಿತಿಯ ಬಟನ್"</string>
<string name="permission_phone" msgid="2661081078692784919">"ಫೋನ್"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"ಸಂಪರ್ಕಗಳು"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ಮೈಕ್ರೊಫೋನ್"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ಕರೆಯ ಲಾಗ್ಗಳು"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳು"</string>
<string name="permission_storage" msgid="6831099350839392343">"ಫೋಟೋಗಳು ಮತ್ತು ಮಾಧ್ಯಮ"</string>
<string name="permission_notification" msgid="693762568127741203">"ಅಧಿಸೂಚನೆಗಳು"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ಆ್ಯಪ್ಗಳು"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನದ ಸ್ಟ್ರೀಮಿಂಗ್"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ಪೋನ್ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಓದಬಹುದು ಮತ್ತು ಬರೆಯಬಹುದು"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ವೀಕ್ಷಿಸಬಹುದು"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಅನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಆಡಿಯೋವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ಸಮೀಪದಲ್ಲಿರುವ ಸಾಧನಗಳನ್ನು ಹುಡುಕಬಹುದು, ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಆಗಬಹುದು ಮತ್ತು ಅವುಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಬಹುದು"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"ಸಂಪರ್ಕಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ಫೋಟೋಗಳಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ಓದಬಹುದು"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ನಿಮ್ಮ ಫೋನ್ನ ಆ್ಯಪ್ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಿ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index ce47b82..190ad22 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"허용 안함"</string>
<string name="consent_back" msgid="2560683030046918882">"뒤로"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>에 설치된 앱에 <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>에 설치된 앱과 동일한 권한을 부여하시겠습니까?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>여기에는 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>의 마이크, 카메라, 위치 정보 액세스 권한 및 기타 민감한 권한이 포함될 수 있습니다.</p> <p>언제든지 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>의 설정에서 이러한 권한을 변경할 수 있습니다.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"여기에는 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>의 <strong>마이크</strong>, <strong>카메라</strong>, <strong>위치 정보 액세스</strong> 및 기타 민감한 권한이 포함될 수 있습니다. <br/><br/>언제든지 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>의 설정에서 이러한 권한을 변경할 수 있습니다."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"앱 아이콘"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"추가 정보 버튼"</string>
<string name="permission_phone" msgid="2661081078692784919">"전화"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"연락처"</string>
<string name="permission_calendar" msgid="6805668388691290395">"캘린더"</string>
<string name="permission_microphone" msgid="2152206421428732949">"마이크"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"통화 기록"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"근처 기기"</string>
<string name="permission_storage" msgid="6831099350839392343">"사진 및 미디어"</string>
<string name="permission_notification" msgid="693762568127741203">"알림"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"앱"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"근처 기기 스트리밍"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"전화를 걸고 통화를 관리할 수 있습니다."</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"통화 기록을 읽고 쓸 수 있습니다."</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS 메시지를 전송하고 볼 수 있습니다."</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"연락처에 액세스할 수 있습니다."</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"캘린더에 액세스할 수 있습니다."</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"마이크를 사용하여 오디오를 녹음할 수 있습니다."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"근처 기기를 찾아 연결하고 기기 간 상대적 위치를 파악할 수 있습니다."</string>
<string name="permission_notification_summary" msgid="884075314530071011">"연락처, 메시지, 사진 등의 정보를 포함한 모든 알림을 읽을 수 있습니다."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"휴대전화의 앱을 스트리밍합니다."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 07ef58d..8bd9a9c 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Уруксат берилбесин"</string>
<string name="consent_back" msgid="2560683030046918882">"Артка"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> түзмөгүнө да <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> түзмөгүнө берилген уруксаттар берилсинби?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Бул уруксаттарга микрофонду жана камераны пайдалануу мүмкүнчүлүгү, ошондой эле кайда жүргөнүңүздү жана <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> түзмөгүндөгү башка купуя маалыматты көрүү мүмкүнчүлүгү кириши мүмкүн.</p> <p>Бул уруксаттарды каалаган убакта <xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g> түзмөгүндөгү Параметрлерден өзгөртө аласыз.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Буга <strong>Микрофонду</strong>, <strong>Камераны</strong> пайдалануу жана <strong>Жайгашкан жерди аныктоо</strong>, ошондой эле <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> түзмөгүндөгү башка купуя маалыматты көрүүгө уруксаттар кириши мүмкүн. <br/><br/>Каалаган убакта <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> түзмөгүндөгү параметрлерге өтүп, бул уруксаттарды өзгөртө аласыз."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Колдонмонун сүрөтчөсү"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дагы маалымат баскычы"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Байланыштар"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Жылнаама"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Чалуулар тизмеси"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Жакын жердеги түзмөктөр"</string>
<string name="permission_storage" msgid="6831099350839392343">"Сүрөттөр жана медиафайлдар"</string>
<string name="permission_notification" msgid="693762568127741203">"Билдирмелер"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Колдонмолор"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Жакын жердеги түзмөктөрдө алып ойнотуу"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Телефон чалууларды аткарып жана тескей алат"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Телефондогу чалуулар тизмесин окуп жана жаза алат"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS билдирүүлөрдү жөнөтүп жана көрө алат"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Байланыштарыңызга кире алат"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Жылнаамаңызга кире алат"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Микрофон аркылуу аудио жаздыра алат"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Жакын жердеги түзмөктөрдү таап, аларга туташып, абалын аныктай алат"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Бардык билдирмелерди, анын ичинде байланыштар, билдирүүлөр жана сүрөттөр сыяктуу маалыматты окуй алат"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Телефондогу колдонмолорду алып ойнотуу"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 0ffe6b9..f093aba 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ບໍ່ອະນຸຍາດ"</string>
<string name="consent_back" msgid="2560683030046918882">"ກັບຄືນ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ໃຫ້ການອະນຸຍາດແອັບຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ເປັນການອະນຸຍາດດຽວກັນກັບຢູ່ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ບໍ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ນີ້ອາດຮວມສິດເຂົ້າເຖິງໄມໂຄຣໂຟນ, ກ້ອງຖ່າຍຮູບ ແລະ ສະຖານທີ່, ຮວມທັງການອະນຸຍາດທີ່ລະອຽດອ່ອນອື່ນໆຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>ທ່ານສາມາດປ່ຽນການອະນຸຍາດເຫຼົ່ານີ້ຕອນໃດກໍໄດ້ໃນການຕັ້ງຄ່າຂອງທ່ານຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ສິ່ງນີ້ອາດຮວມມີສິດເຂົ້າເຖິງ <strong>ໄມໂຄຣໂຟນ</strong>, <strong>ກ້ອງຖ່າຍຮູບ</strong> ແລະ <strong>ສະຖານທີ່</strong> ພ້ອມທັງການອະນຸຍາດທີ່ລະອຽດອ່ອນອື່ນໆຢູ່ໃນ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>ທ່ານສາມາດປ່ຽນແປງສິດການອະນຸຍາດເຫຼົ່ານີ້ໄດ້ທຸກເວລາໃນການຕັ້ງຄ່າຂອງທ່ານຢູ່ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ໄອຄອນແອັບ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ປຸ່ມຂໍ້ມູນເພີ່ມເຕີມ"</string>
<string name="permission_phone" msgid="2661081078692784919">"ໂທລະສັບ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"ລາຍຊື່ຜູ້ຕິດຕໍ່"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ປະຕິທິນ"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ໄມໂຄຣໂຟນ"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ບັນທຶກການໂທ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ຮູບພາບ ແລະ ມີເດຍ"</string>
<string name="permission_notification" msgid="693762568127741203">"ການແຈ້ງເຕືອນ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ແອັບ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ການສະຕຣີມອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ສາມາດໂທອອກ ແລະ ຈັດການການໂທໄດ້"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ສາມາດອ່ານ ແລະ ຂຽນບັນທຶກການໂທຂອງໂທລະສັບ"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"ສາມາດສົ່ງ ແລະ ເບິ່ງຂໍ້ຄວາມ SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ສາມາດເຂົ້າເຖິງລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ສາມາດເຂົ້າເຖິງປະຕິທິນຂອງທ່ານ"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"ສາມາດບັນທຶກສຽງໂດຍນຳໃຊ້ໄມໂຄຣໂຟນໄດ້"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ສາມາດຊອກຫາ, ເຊື່ອມຕໍ່ ແລະ ລະບຸສະຖານທີ່ທີ່ກ່ຽວຂ້ອງກັນຂອງອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງ"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"ສາມາດອ່ານການແຈ້ງເຕືອນທັງໝົດ, ຮວມທັງຂໍ້ມູນ ເຊັ່ນ: ລາຍຊື່ຜູ້ຕິດຕໍ່, ຂໍ້ຄວາມ ແລະ ຮູບພາບ"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ສະຕຣີມແອັບຂອງໂທລະສັບທ່ານ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index a1b5def..7c74c69 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Neleisti"</string>
<string name="consent_back" msgid="2560683030046918882">"Atgal"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Suteikti <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> esančioms programoms tuos pačius leidimus kaip <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> esančioms programoms?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Gali būti įtraukti prieigos prie mikrofono, kameros ir vietovės leidimai ir kiti leidimai pasiekti neskelbtiną informaciją <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> įrenginyje.</p> <p>Šiuos leidimus galite bet kada pakeisti „Nustatymų“ skiltyje <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> įrenginyje.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Tai gali apimti <strong>mikrofono</strong>, <strong>fotoaparato</strong>, ir <strong>prieigos prie vietovės</strong>, leidimus bei kitus leidimus pasiekti neskelbtiną informaciją įrenginyje <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Šiuos leidimus galite bet kada pakeisti įrenginio <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> nustatymų skiltyje."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Programos piktograma"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Mygtukas „Daugiau informacijos“"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefonas"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktai"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendorius"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofonas"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Skambučių žurnalai"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Įrenginiai netoliese"</string>
<string name="permission_storage" msgid="6831099350839392343">"Nuotraukos ir medija"</string>
<string name="permission_notification" msgid="693762568127741203">"Pranešimai"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Programos"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Perdav. įrenginiams netoliese"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Gali atlikti ir tvarkyti telefono skambučius"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Gali skaityti ir rašyti telefono skambučių žurnalą"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Gali siųsti ir peržiūrėti SMS pranešimus"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Gali pasiekti jūsų kontaktus"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Gali pasiekti jūsų kalendorių"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Naudojant šį mikrofoną negalima įrašyti garso"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Gali rasti apytikslę netoliese esančių įrenginių poziciją, aptikti juos ir prisijungti prie jų"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Galima skaityti visus pranešimus, įskaitant tokią informaciją kaip kontaktai, pranešimai ir nuotraukos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefono programų perdavimas srautu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 232afa59..15cce52 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Neatļaut"</string>
<string name="consent_back" msgid="2560683030046918882">"Atpakaļ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vai lietotnēm ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> piešķirt tādas pašas atļaujas kā ierīcē <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Tās var būt mikrofona, kameras, atrašanās vietas piekļuves atļaujas un citas sensitīvas atļaujas ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Atļaujas jebkurā brīdī varat mainīt ierīces <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> iestatījumos.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Tās var būt <strong>mikrofona</strong>, <strong>kameras</strong>, <strong>atrašanās vietas piekļuves</strong> atļaujas, kā arī citas sensitīvas atļaujas ierīcē <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Atļaujas varat jebkurā brīdī mainīt ierīces <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> iestatījumos."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Lietotnes ikona"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Plašākas informācijas poga"</string>
<string name="permission_phone" msgid="2661081078692784919">"Tālrunis"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktpersonas"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendārs"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofons"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Zvanu žurnāli"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Tuvumā esošas ierīces"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotoattēli un multivides faili"</string>
<string name="permission_notification" msgid="693762568127741203">"Paziņojumi"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Lietotnes"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Straumēšana ierīcēs tuvumā"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Var veikt un pārvaldīt tālruņa zvanus"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Var lasīt un rakstīt tālruņa zvanu žurnālu"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Var sūtīt un skatīt īsziņas"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Var piekļūt jūsu kontaktpersonām"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Var piekļūt jūsu kalendāram"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Var ierakstīt audio, izmantojot mikrofonu"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Var atrast tuvumā esošas ierīces, izveidot ar tām savienojumu un noteikt to relatīvo atrašanās vietu"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Var lasīt visus paziņojumus, tostarp tādu informāciju kā kontaktpersonas, ziņojumi un fotoattēli."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Straumēt jūsu tālruņa lietotnes"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 43716e3..73afafac 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Не дозволувај"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Дасе дадат исти дозволи на апликациите на <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> како на <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ова може да вклучува пристап до микрофон, камера и локација и други чувствителни дозволи на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Може да ги промените дозволиве во секое време во вашите „Поставки“ на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ова може да вклучува дозволи за пристап до <strong>микрофонот</strong>, <strong>камерата</strong> и <strong>локацијата</strong>, како и други чувствителни дозволи на <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Дозволиве може да ги промените во секое време во „Поставки“ на <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона на апликацијата"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Копче за повеќе информации"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Евиденција на повици"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Уреди во близина"</string>
<string name="permission_storage" msgid="6831099350839392343">"Аудиовизуелни содржини"</string>
<string name="permission_notification" msgid="693762568127741203">"Известувања"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Апликации"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Стриминг на уреди во близина"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Може да упатува и управува со телефонски повици"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чита и пишува евиденција на повици во телефонот"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Може да испраќа и гледа SMS-пораки"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Може да пристапува до вашите контакти"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да пристапува до вашиот календар"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Може да снима аудио со микрофонот"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да наоѓа и да се поврзува со уреди во близина и да ја утврдува нивната релативна положба"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"може да ги чита сите известувања, вклучително и податоци како контакти, пораки и фотографии"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримувајте ги апликациите на телефонот"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 430b936..0644dd9 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"അനുവദിക്കരുത്"</string>
<string name="consent_back" msgid="2560683030046918882">"മടങ്ങുക"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> എന്നതിലെ അതേ അനുമതികൾ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> എന്നതിലെ ആപ്പുകൾക്ക് നൽകണോ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> എന്നതിലെ മൈക്രോഫോൺ, ക്യാമറ, ലൊക്കേഷൻ ആക്സസ്, സെൻസിറ്റീവ് വിവരങ്ങൾക്കുള്ള മറ്റ് അനുമതികൾ എന്നിവയും ഇതിൽ ഉൾപ്പെട്ടേക്കാം<p>നിങ്ങൾക്ക് <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> എന്നതിലെ ക്രമീകരണത്തിൽ ഏതുസമയത്തും ഈ അനുമതികൾ മാറ്റാം."</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. എന്നതിലെ <strong>മൈക്രോഫോൺ</strong>, <strong>ക്യാമറ</strong>, and <strong>ലൊക്കേഷൻ ആക്സസ്</strong>, സെൻസിറ്റീവ് വിവരങ്ങൾക്കുള്ള മറ്റ് അനുമതികൾ എന്നിവയും ഇതിൽ ഉൾപ്പെട്ടേക്കാം. <br/><br/>നിങ്ങൾക്ക് <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> എന്നതിലെ ക്രമീകരണത്തിൽ ഏതുസമയത്തും ഈ അനുമതികൾ മാറ്റാം."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ആപ്പ് ഐക്കൺ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"കൂടുതൽ വിവരങ്ങൾ ബട്ടൺ"</string>
<string name="permission_phone" msgid="2661081078692784919">"ഫോൺ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"മൈക്രോഫോൺ"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"കോൾ ചരിത്രം"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"സമീപമുള്ള ഉപകരണങ്ങൾ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ഫോട്ടോകളും മീഡിയയും"</string>
<string name="permission_notification" msgid="693762568127741203">"അറിയിപ്പുകൾ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ആപ്പുകൾ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"സമീപമുള്ള ഉപകരണ സ്ട്രീമിംഗ്"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ഫോൺ കോളുകൾ ചെയ്യാനും അവ മാനേജ് ചെയ്യാനും കഴിയും"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ഫോൺ കോൾ ചരിത്രം റീഡ് ചെയ്യാനും റൈറ്റ് ചെയ്യാനും കഴിയും"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS സന്ദേശങ്ങൾ അയയ്ക്കാനും കാണാനും കഴിയും"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്സസ് ചെയ്യാൻ കഴിയും"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"നിങ്ങളുടെ കലണ്ടർ ആക്സസ് ചെയ്യാൻ കഴിയും"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"മൈക്രോഫോൺ ഉപയോഗിച്ച് ഓഡിയോ റെക്കോർഡ് ചെയ്യാം"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"സമീപമുള്ള ഉപകരണങ്ങൾ കണ്ടെത്താനും അവയിലേക്ക് കണക്റ്റ് ചെയ്യാനും അവയുടെ ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും കഴിയും"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"കോൺടാക്റ്റുകൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ മുതലായ വിവരങ്ങൾ ഉൾപ്പെടെയുള്ള എല്ലാ അറിയിപ്പുകളും വായിക്കാനാകും"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"നിങ്ങളുടെ ഫോണിലെ ആപ്പുകൾ സ്ട്രീം ചെയ്യുക"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index cf781d4..d57b4d3 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Бүү зөвшөөр"</string>
<string name="consent_back" msgid="2560683030046918882">"Буцах"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> дээрх аппуудад <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> дээрхтэй адил зөвшөөрөл өгөх үү?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Үүнд Микрофон, Камер болон Байршлын хандалт болон <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> дээрх бусад эмзэг зөвшөөрөл багтаж болно.</p> <p>Та эдгээр зөвшөөрлийг <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> дээрх Тохиргоо хэсэгтээ хүссэн үедээ өөрчлөх боломжтой.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Үүнд <strong>Микрофон</strong>, <strong>Камер</strong>,, <strong>Байршлын хандалт</strong> болон <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> дээрх бусад эмзэг зөвшөөрөл багтаж болно. <br/><br/>Та эдгээр зөвшөөрлийг <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> дээрх Тохиргоондоо хүссэн үедээ өөрчлөх боломжтой."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Aппын дүрс тэмдэг"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дэлгэрэнгүй мэдээллийн товчлуур"</string>
<string name="permission_phone" msgid="2661081078692784919">"Утас"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Харилцагчид"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календарь"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Дуудлагын жагсаалт"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Ойролцоох төхөөрөмжүүд"</string>
<string name="permission_storage" msgid="6831099350839392343">"Зураг болон медиа"</string>
<string name="permission_notification" msgid="693762568127741203">"Мэдэгдэл"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Аппууд"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ойролцоох төхөөрөмжид дамжуул"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Дуудлага хийх, удирдах боломжтой"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Утасны дуудлагын жагсаалтыг уншиж, бичих боломжтой"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS мессеж илгээх, үзэх боломжтой"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Таны харилцагчдад хандах боломжтой"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Таны календарьт хандах боломжтой"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Микрофоныг ашиглан аудио бичих боломжтой"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Ойролцоох төхөөрөмжүүдийн харьцангуй байршлыг тодорхойлох, холбох, олох боломжтой"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Харилцагчид, мессеж болон зураг зэрэг мэдээллийг оруулаад бүх мэдэгдлийг унших боломжтой"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Утасныхаа аппуудыг дамжуулаарай"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index f67561e..70b0567 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"अनुमती देऊ नका"</string>
<string name="consent_back" msgid="2560683030046918882">"मागे जा"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> वरील अॅप्सना <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> प्रमाणेच परवानग्या द्यायच्या आहेत का?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>यामध्ये <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g><strong> वरील मायक्रोफोन, कॅमेरा आणि स्थान अॅक्सेस व इतर संवेदनशील परवानग्यांचा समावेश असू शकतो </strong>.</p> <p>तुम्ही <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> वर तुमच्या सेटिंग्ज मध्ये या परवानग्या कधीही बदलू शकता</strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"यामध्ये पुढील गोष्टी समाविष्ट असू शकतात <strong>मायक्रोफोन</strong>, <strong>कॅमेरा</strong>, and <strong>स्थान अॅक्सेस</strong>, आणि <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> वरील इतर संवेदनशील परवानग्या. <br/><br/>तुम्ही <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> वर तुमच्या सेटिंग्ज मध्ये कोणत्याही वेळेला या परवानग्या बदलू शकता."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"अॅप आयकन"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"अधिक माहिती बटण"</string>
<string name="permission_phone" msgid="2661081078692784919">"फोन"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"मायक्रोफोन"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"कॉल लॉग"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"जवळपासची डिव्हाइस"</string>
<string name="permission_storage" msgid="6831099350839392343">"फोटो आणि मीडिया"</string>
<string name="permission_notification" msgid="693762568127741203">"सूचना"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ॲप्स"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"जवळपासच्या डिव्हाइसवरील स्ट्रीमिंग"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"फोन कॉल करू आणि व्यवस्थापित करू शकते"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"फोन कॉल लॉग रीड अँड राइट करू शकते"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"एसएमएस मेसेज पाठवू आणि पाहू शकते"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"तुमचे संपर्क अॅक्सेस करू शकते"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"तुमचे कॅलेंडर अॅक्सेस करू शकते"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"मायक्रोफोन वापरून ऑडिओ रेकॉर्ड करता येईल"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"जवळील डिव्हाइस शोधू शकते, त्यांच्याशी कनेक्ट करू शकते आणि त्यांचे संबंधित स्थान निर्धारित करू शकते"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"संपर्क, मेसेज आणि फोटो यांसारख्या माहितीचा समावेश असलेल्या सर्व सूचना वाचू शकते"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"तुमच्या फोनवरील ॲप्स स्ट्रीम करा"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index fd1c488..436ff9c 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Jangan benarkan"</string>
<string name="consent_back" msgid="2560683030046918882">"Kembali"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Beri apl pada <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> kebenaran yang sama seperti pada <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Ini mungkin termasuk akses Mikrofon, Kamera dan Lokasi serta kebenaran sensitif lain pada <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Anda boleh menukar kebenaran ini pada bila-bila masa dalam Tetapan anda pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ini mungkin termasuk <strong>Mikrofon</strong>, <strong>Kamera</strong> dan <strong>Akses lokasi</strong> serta kebenaran sensitif lain pada <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Anda boleh menukar kebenaran ini pada bila-bila masa dalam Tetapan anda pada <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikon Apl"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butang Maklumat Lagi"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kenalan"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Log panggilan"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Peranti berdekatan"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto dan media"</string>
<string name="permission_notification" msgid="693762568127741203">"Pemberitahuan"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apl"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Penstriman Peranti Berdekatan"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Boleh membuat dan mengurus panggilan telefon"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Boleh membaca dan menulis log panggilan telefon"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Boleh menghantar dan melihat mesej SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Boleh mengakses kenalan anda"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Boleh mengakses kalendar anda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Boleh merakam audio menggunakan mikrofon"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Boleh mencari, menyambung dan menentukan kedudukan relatif peranti berdekatan"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Boleh membaca semua pemberitahuan, termasuk maklumat seperti kenalan, mesej dan foto"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Strim apl telefon anda"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 9df27a0..eb03fb2 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ခွင့်မပြုပါ"</string>
<string name="consent_back" msgid="2560683030046918882">"နောက်သို့"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"အက်ပ်များကို <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> တွင်ပေးထားသည့် ခွင့်ပြုချက်များအတိုင်း <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> တွင် ပေးမလား။"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>၎င်းတွင် မိုက်ခရိုဖုန်း၊ ကင်မရာ၊ တည်နေရာ အသုံးပြုခွင့်အပြင် <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> ပေါ်ရှိ အခြား သတိထားရမည့် ခွင့်ပြုချက်များ ပါဝင်နိုင်သည်။</p> <p>ဤခွင့်ပြုချက်များကို <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ပေါ်ရှိ သင်၏ဆက်တင်များတွင် အချိန်မရွေးပြောင်းနိုင်သည်။</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> တွင် <strong>မိုက်ခရိုဖုန်း</strong>၊ <strong>ကင်မရာ</strong>၊ <strong>တည်နေရာသုံးခွင့်</strong> နှင့် အခြားသတိထားရမည့် ခွင့်ပြုချက်များ ပါဝင်နိုင်သည်။ <br/><br/>ဤခွင့်ပြုချက်များကို <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> ရှိ ဆက်တင်များတွင် အချိန်မရွေး ပြောင်းနိုင်သည်။"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"အက်ပ်သင်္ကေတ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"နောက်ထပ်အချက်အလက်များ ခလုတ်"</string>
<string name="permission_phone" msgid="2661081078692784919">"ဖုန်း"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"အဆက်အသွယ်များ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ပြက္ခဒိန်"</string>
<string name="permission_microphone" msgid="2152206421428732949">"မိုက်ခရိုဖုန်း"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ခေါ်ဆိုမှတ်တမ်း"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"အနီးတစ်ဝိုက်ရှိ စက်များ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ဓာတ်ပုံနှင့် မီဒီယာများ"</string>
<string name="permission_notification" msgid="693762568127741203">"အကြောင်းကြားချက်များ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"အက်ပ်များ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"အနီးရှိစက်တိုက်ရိုက်ဖွင့်ခြင်း"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ဖုန်းခေါ်ဆိုမှုများကို ပြုလုပ်ခြင်းနှင့် စီမံခြင်းတို့ လုပ်နိုင်သည်"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ဖုန်းခေါ်ဆိုမှတ်တမ်းကို ဖတ်ခြင်းနှင့် ရေးခြင်းတို့ လုပ်နိုင်သည်"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS မက်ဆေ့ဂျ်များကို ပို့ခြင်းနှင့် ကြည့်ရှုခြင်းတို့ လုပ်နိုင်သည်"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"သင့်အဆက်အသွယ်များကို ဝင်ကြည့်နိုင်သည်"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"သင့်ပြက္ခဒိန်ကို သုံးနိုင်သည်"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"မိုက်ခရိုဖုန်းသုံးပြီး အသံဖမ်းနိုင်သည်"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"အနီးတစ်ဝိုက်ရှိ စက်များ၏ ဆက်စပ်နေရာကို ရှာခြင်း၊ ချိတ်ဆက်ခြင်းနှင့် သတ်မှတ်ခြင်းတို့ လုပ်နိုင်သည်"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"အဆက်အသွယ်၊ မက်ဆေ့ဂျ်နှင့် ဓာတ်ပုံကဲ့သို့ အချက်အလက်များအပါအဝင် အကြောင်းကြားချက်အားလုံးကို ဖတ်နိုင်သည်"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"သင့်ဖုန်းရှိအက်ပ်များကို တိုက်ရိုက်ဖွင့်နိုင်သည်"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 1010cd2..76c75617 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ikke tillat"</string>
<string name="consent_back" msgid="2560683030046918882">"Tilbake"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vil du gi apper på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> de samme tillatelsene som på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dette kan inkludere tilgang til mikrofon, kamera og posisjon samt andre sensitive tillatelser på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan når som helst endre disse tillatelsene i innstillingene på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Dette kan inkludere <strong>mikrofon</strong>-, <strong>kamera</strong>- og <strong>posisjonstilgang</strong> samt andre sensitive tillatelser på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Du kan når som helst endre disse tillatelsene i innstillingene på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Mer informasjon-knapp"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Samtalelogger"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i nærheten"</string>
<string name="permission_storage" msgid="6831099350839392343">"Bilder og medier"</string>
<string name="permission_notification" msgid="693762568127741203">"Varsler"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apper"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strøm til enheter i nærheten"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Kan ringe ut og administrere anrop"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan lese og skrive samtaleloggen"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sende og lese SMS-meldinger"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kan bruke kontaktene dine"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Kan bruke kalenderen din"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Kan ta opp lyd med mikrofonen"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan finne, koble til og fastslå den relative posisjonen til enheter i nærheten"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan lese alle varsler, inkludert informasjon som kontakter, meldinger og bilder"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Strøm appene på telefonen"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 427a5f1..149cbce 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"अनुमति नदिनुहोस्"</string>
<string name="consent_back" msgid="2560683030046918882">"पछाडि"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> मा भएका एपहरूलाई पनि <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> मा दिइएकै अनुमति दिने हो?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>यसअन्तर्गत <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> का माइक्रोफोन, क्यामेरा र लोकेसन प्रयोग गर्ने अनुमतिका साथसाथै अन्य संवेदनशील अनुमति समावेश हुन सक्छन्।</p> <p>तपाईं <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> का सेटिङमा गई जुनसुकै बेला यी अनुमति परिवर्तन गर्न सक्नुहुन्छ।</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"यसअन्तर्गत <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> का <strong>माइक्रोफोन</strong>, <strong>क्यामेरा</strong> र <strong>लोकेसन प्रयोग गर्ने अनुमति</strong> तथा अन्य संवेदनशील अनुमतिहरू समावेश हुन्छन्। <br/><br/>तपाईं जुनसुकै बेला <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> का सेटिङमा गई यी अनुमति परिवर्तन गर्न सक्नुहुन्छ।"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"एपको आइकन"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"थप जानकारी देखाउने बटन"</string>
<string name="permission_phone" msgid="2661081078692784919">"फोन"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacts"</string>
<string name="permission_calendar" msgid="6805668388691290395">"पात्रो"</string>
<string name="permission_microphone" msgid="2152206421428732949">"माइक्रोफोन"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"कल लगहरू"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"नजिकैका डिभाइसहरू"</string>
<string name="permission_storage" msgid="6831099350839392343">"फोटो र मिडिया"</string>
<string name="permission_notification" msgid="693762568127741203">"सूचनाहरू"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"एपहरू"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"नजिकैको डिभाइसमा स्ट्रिम गरिँदै छ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"फोन कल गर्न र कलहरू व्यवस्थापन गर्न सक्छ"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"फोनको कल लग रिड र राइट गर्न सक्छ"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS म्यासेजहरू पठाउन र हेर्न सक्छ"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"तपाईंका कन्ट्याक्टहरू हेर्न सक्छ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"तपाईंको पात्रो हेर्न सक्छ"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"यसका सहायताले माइक्रोफोन प्रयोग गरी अडियो रेकर्ड गर्न सकिन्छ"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"नजिकैका डिभाइसहरू भेट्टाउन, ती डिभाइससँग कनेक्ट गर्न र तिनको सापेक्ष स्थिति निर्धारण गर्न सक्छ"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"कन्ट्याक्ट, म्यासेज र फोटोलगायतका जानकारीसहित सबै सूचनाहरू पढ्न सक्छ"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"आफ्नो फोनका एपहरू प्रयोग गर्नुहोस्"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 1da394e..c9106c3 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Niet toestaan"</string>
<string name="consent_back" msgid="2560683030046918882">"Terug"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Apps op de <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> dezelfde rechten geven als op de <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Dit kan toegang tot de microfoon, camera en je locatie en andere gevoelige rechten op je <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> omvatten.</p> <p>Je kunt deze rechten op elk moment wijzigen in je Instellingen op de <xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Dit kan <strong>Microfoon</strong>, <strong>Camera</strong> en <strong>Locatietoegang</strong> en andere gevoelige rechten op de <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> omvatten. <br/><br/>Je kunt deze rechten altijd wijzigen in je Instellingen op de <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"App-icoon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knop Meer informatie"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefoon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contacten"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfoon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Gesprekslijsten"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Apparaten in de buurt"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foto\'s en media"</string>
<string name="permission_notification" msgid="693762568127741203">"Meldingen"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming op apparaten in de buurt"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Kan telefoongesprekken starten en beheren"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Kan gesprekslijst lezen en ernaar schrijven"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Kan sms-berichten sturen en bekijken"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Heeft toegang tot je contacten"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Heeft toegang tot je agenda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Kan audio opnemen met de microfoon"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Kan apparaten in de buurt vinden, er verbinding mee maken en de relatieve positie ervan bepalen"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan alle meldingen lezen, waaronder informatie zoals contacten, berichten en foto\'s"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Stream de apps van je telefoon"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 23d88d3..519e711 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
<string name="consent_back" msgid="2560683030046918882">"ପଛକୁ ଫେରନ୍ତୁ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>ପରି <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>ରେ ଥିବା ଆପ୍ସକୁ ସମାନ ଅନୁମତିଗୁଡ଼ିକ ଦେବେ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ଏହା <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ରେ ମାଇକ୍ରୋଫୋନ, କ୍ୟାମେରା ଏବଂ ଲୋକେସନ ଆକ୍ସେସ ଓ ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ଅନୁମତିଗୁଡ଼ିକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ।</p> <p>ଆପଣ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ରେ ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ସେଟିଂସରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ଏହା <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>ରେ <strong>ମାଇକ୍ରୋଫୋନ</strong>, <strong>କେମେରା</strong>, ଏବଂ <strong>ଲୋକେସନ ଆକ୍ସେସ</strong> ଏବଂ ଅନ୍ୟ ସମ୍ବେଦନଶୀଳ ଅନୁମତିଗୁଡ଼ିକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରିପାରେ। <br/><br/>ଆପଣ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>ରେ ଯେ କୌଣସି ସମୟରେ ଆପଣଙ୍କ ସେଟିଂସରେ ଏହି ଅନୁମତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ଆପ ଆଇକନ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ଅଧିକ ସୂଚନା ବଟନ"</string>
<string name="permission_phone" msgid="2661081078692784919">"ଫୋନ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"କଣ୍ଟାକ୍ଟଗୁଡ଼ିକ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"କେଲେଣ୍ଡର"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ମାଇକ୍ରୋଫୋନ"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"କଲ ଲଗଗୁଡ଼ିକ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ଫଟୋ ଏବଂ ମିଡିଆ"</string>
<string name="permission_notification" msgid="693762568127741203">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ଆପ୍ସ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ଆଖପାଖର ଡିଭାଇସରେ ଷ୍ଟ୍ରିମିଂ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ଫୋନ କଲଗୁଡ଼ିକ କରିପାରିବ ଏବଂ ସେଗୁଡ଼ିକୁ ପରିଚାଳନା କରିପାରିବ"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ଫୋନ କଲ ଲଗକୁ ପଢ଼ିପାରିବ ଏବଂ ଲେଖିପାରିବ"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ମେସେଜଗୁଡ଼ିକ ପଠାଇପାରିବ ଏବଂ ଦେଖିପାରିବ"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ଆପଣଙ୍କ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିପାରିବ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ଆପଣଙ୍କ କେଲେଣ୍ଡରକୁ ଆକ୍ସେସ କରିପାରିବ"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"ମାଇକ୍ରୋଫୋନକୁ ବ୍ୟବହାର କରି ଅଡିଓ ରେକର୍ଡ କରାଯାଇପାରିବ"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକୁ ଖୋଜିପାରିବ, କନେକ୍ଟ କରିପାରିବ ଏବଂ ସେଗୁଡ଼ିକର ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ନିର୍ଦ୍ଧାରଣ କରିପାରିବ"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"ଯୋଗାଯୋଗ, ମେସେଜ ଏବଂ ଫଟୋଗୁଡ଼ିକ ପରି ସୂଚନା ସମେତ ସମସ୍ତ ବିଜ୍ଞପ୍ତିକୁ ପଢ଼ିପାରିବ"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ଆପଣଙ୍କ ଫୋନର ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରନ୍ତୁ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 63744a1..8bc9e94 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
<string name="consent_back" msgid="2560683030046918882">"ਪਿੱਛੇ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ਕੀ <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਐਪਾਂ ਨੂੰ <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਐਪਾਂ ਵਾਂਗ ਇਜਾਜ਼ਤਾਂ ਦੇਣੀਆਂ ਹਨ?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>ਇਸ ਵਿੱਚ ਮਾਈਕ੍ਰੋਫ਼ੋਨ, ਕੈਮਰਾ, ਟਿਕਾਣਾ ਪਹੁੰਚ ਅਤੇ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀਆਂ ਹਨ।</p> <p>ਤੁਸੀਂ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਦੇ ਵੀ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"ਇਸ ਵਿੱਚ <strong>ਮਾਈਕ੍ਰੋਫ਼ੋਨ</strong>, <strong>ਕੈਮਰਾ</strong>, ਅਤੇ <strong>ਟਿਕਾਣਾ ਪਹੁੰਚ</strong>, ਅਤੇ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਹੋਰ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਸੰਬੰਧੀ ਇਜਾਜ਼ਤਾਂ ਸ਼ਾਮਲ ਹੋ ਸਕਦੀਆਂ ਹਨ। <br/><br/>ਤੁਸੀਂ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> \'ਤੇ ਮੌਜੂਦ ਆਪਣੀਆਂ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਕਿਸੇ ਵੀ ਵੇਲੇ ਇਨ੍ਹਾਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ਐਪ ਪ੍ਰਤੀਕ"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ਹੋਰ ਜਾਣਕਾਰੀ ਬਟਨ"</string>
<string name="permission_phone" msgid="2661081078692784919">"ਫ਼ੋਨ"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"ਸੰਪਰਕ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ਕੈਲੰਡਰ"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ਕਾਲ ਲੌਗ"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸ"</string>
<string name="permission_storage" msgid="6831099350839392343">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ"</string>
<string name="permission_notification" msgid="693762568127741203">"ਸੂਚਨਾਵਾਂ"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ਐਪਾਂ"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸਟ੍ਰੀਮਿੰਗ"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ਫ਼ੋਨ ਦੇ ਕਾਲ ਲੌਗ ਨੂੰ ਪੜ੍ਹਣ ਅਤੇ ਲਿਖਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS ਸੁਨੇਹੇ ਭੇਜਣ ਅਤੇ ਦੇਖਣ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ਆਪਣੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕਦੇ ਹੋ"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਨੂੰ ਲੱਭਣ, ਉਨ੍ਹਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਹੈ"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"ਤੁਸੀਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਪੜ੍ਹ ਸਕਦੇ ਹੋ, ਜਿਨ੍ਹਾਂ ਵਿੱਚ ਸੰਪਰਕਾਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਫ਼ੋਟੋਆਂ ਵਰਗੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੁੰਦੀ ਹੈ"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ਆਪਣੇ ਫ਼ੋਨ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰੋ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index 167a050..2fc8a47 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nie zezwalaj"</string>
<string name="consent_back" msgid="2560683030046918882">"Wstecz"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Czy aplikacjom na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> przyznać te same uprawnienia co na urządzeniu <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mogą one obejmować dostęp do Mikrofonu, Aparatu i lokalizacji oraz inne uprawnienia newralgiczne na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Możesz w dowolnym momencie zmienić uprawnienia na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Wśród nich mogą być dane dostępu do <strong>Mikrofonu</strong>, <strong>Aparatu</strong>, i <strong>Lokalizacji</strong>, i inne uprawnienia newralgiczne na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Możesz w dowolnym momencie zmienić uprawnienia na urządzeniu <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacji"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Przycisk – więcej informacji"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendarz"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Rejestry połączeń"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Urządzenia w pobliżu"</string>
<string name="permission_storage" msgid="6831099350839392343">"Zdjęcia i multimedia"</string>
<string name="permission_notification" msgid="693762568127741203">"Powiadomienia"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacje"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Strumieniowanie danych na urządzenia w pobliżu"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Może wykonywać i odbierać połączenia"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Może odczytywać i zapisywać rejestr połączeń telefonicznych"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Może wysyłać i odbierać SMS-y"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Może uzyskać dostęp do kontaktów"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Może uzyskać dostęp do kalendarza"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Może nagrywać dźwięk przy użyciu mikrofonu"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Może znajdować urządzenia w pobliżu, określać ich względne położenie oraz łączyć się z nimi"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Może odczytywać wszystkie powiadomienia, w tym informacje takie jak kontakty, wiadomości i zdjęcia"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Odtwarzaj strumieniowo aplikacje z telefonu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index e29e785..aa054a8 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dar aos apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas permissões do dispositivo <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isso inclui acesso a microfone, câmera e localização e outras permissões sensíveis no <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Você pode mudar a qualquer momento nas configurações do <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Isso pode incluir acesso ao <strong>Microfone</strong>, à <strong>Câmera</strong> e à <strong>Localização</strong>, além de outras permissões sensíveis no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Você pode mudar essas permissões a qualquer momento nas Configurações do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícone do app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botão \"Mais informações\""</string>
<string name="permission_phone" msgid="2661081078692784919">"Smartphone"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contatos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registro de chamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos por perto"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming em disp. por perto"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerenciar ligações"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e gravar o registro de chamadas"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e acessar mensagens SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acessar seus contatos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acessar sua agenda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Pode gravar áudio usando o microfone"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, determinar o posicionamento relativo e se conectar a dispositivos por perto"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 66bf220..852d994 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dar às apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas autorizações de <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isto pode incluir o acesso ao microfone, câmara e localização, bem como a outras autorizações confidenciais no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Pode alterar estas autorizações em qualquer altura nas Definições do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Isto pode incluir o acesso ao <strong>microfone</strong>, <strong>câmara</strong>, e <strong>localização</strong>, bem como outras autorizações confidenciais no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Pode alterar estas autorizações em qualquer altura nas Definições do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícone da app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botão Mais informações"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telemóvel"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contactos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendário"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registos de chamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos próximos"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e multimédia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Stream de dispositivo próximo"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerir chamadas telefónicas"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e escrever o registo de chamadas do telemóvel"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e ver mensagens SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pode aceder aos seus contactos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode aceder ao seu calendário"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Não é possível gravar áudio através do microfone"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, estabelecer ligação e determinar a posição relativa dos dispositivos próximos"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contactos, mensagens e fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Faça stream das apps do telemóvel"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index e29e785..aa054a8 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Não permitir"</string>
<string name="consent_back" msgid="2560683030046918882">"Voltar"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Dar aos apps no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> as mesmas permissões do dispositivo <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Isso inclui acesso a microfone, câmera e localização e outras permissões sensíveis no <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Você pode mudar a qualquer momento nas configurações do <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Isso pode incluir acesso ao <strong>Microfone</strong>, à <strong>Câmera</strong> e à <strong>Localização</strong>, além de outras permissões sensíveis no dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Você pode mudar essas permissões a qualquer momento nas Configurações do dispositivo <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ícone do app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Botão \"Mais informações\""</string>
<string name="permission_phone" msgid="2661081078692784919">"Smartphone"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Contatos"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Agenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfone"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Registro de chamadas"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispositivos por perto"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotos e mídia"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificações"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Apps"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming em disp. por perto"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Pode fazer e gerenciar ligações"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Pode ler e gravar o registro de chamadas"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Pode enviar e acessar mensagens SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Pode acessar seus contatos"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Pode acessar sua agenda"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Pode gravar áudio usando o microfone"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Pode encontrar, determinar o posicionamento relativo e se conectar a dispositivos por perto"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Pode ler todas as notificações, incluindo informações como contatos, mensagens e fotos"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Fazer transmissão dos apps no seu smartphone"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index e527ac1..be66dca 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nu permite"</string>
<string name="consent_back" msgid="2560683030046918882">"Înapoi"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Acorzi aplicațiilor de pe <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> aceleași permisiuni ca pe <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Aici pot fi incluse accesul la microfon, la camera foto, la locație și alte permisiuni de accesare a informațiilor sensibile de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Poți modifica oricând aceste permisiuni din Setările de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Aici pot fi incluse accesul la <strong>microfon</strong>, la <strong>camera foto</strong>, la <strong>locație</strong> și alte permisiuni de accesare a informațiilor sensibile de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Poți modifica oricând aceste permisiuni din Setările de pe <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Pictograma aplicației"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butonul Mai multe informații"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Agendă"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Microfon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Jurnale de apeluri"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Dispozitive din apropiere"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografii și media"</string>
<string name="permission_notification" msgid="693762568127741203">"Notificări"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplicații"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming pe dispozitivele din apropiere"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Poate să facă și să gestioneze apeluri telefonice"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Poate să citească și să scrie în jurnalul de apeluri telefonice"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Poate să trimită și să vadă mesaje SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Poate accesa agenda"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Poate accesa calendarul"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Poate înregistra conținut audio folosind microfonul"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Poate să găsească, să se conecteze la și să determine poziția relativă a dispozitivelor apropiate"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Poate să citească toate notificările, inclusiv informații cum ar fi agenda, mesajele și fotografiile"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Să redea în stream aplicațiile telefonului"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 326d241..8e2aed1 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Запретить"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Предоставить приложениям на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> те же разрешения, что на устройстве <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Сюда может входить доступ к микрофону, камере и данным о местоположении, а также другие разрешения на доступ к конфиденциальной информации на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Вы можете в любое время изменить разрешения в настройках устройства <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"У приложений может появиться доступ к <strong>микрофону</strong>, <strong>камере</strong>, <strong>местоположению</strong> и другой конфиденциальной информации на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Вы можете в любое время изменить разрешения в настройках на устройстве <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Значок приложения"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Кнопка информации"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контакты"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календарь"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Список вызовов"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Устройства поблизости"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фотографии и медиафайлы"</string>
<string name="permission_notification" msgid="693762568127741203">"Уведомления"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Приложения"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Трансляция на устройства рядом"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Приложение сможет совершать вызовы и управлять ими."</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Приложение сможет читать список вызовов и создавать записи в этом списке."</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Приложение сможет отправлять и просматривать SMS."</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Приложение сможет получать доступ к вашему списку контактов."</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Приложение сможет получать доступ к вашему календарю."</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Можно записывать аудио с помощью микрофона"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Приложение сможет находить устройства поблизости, подключаться к ним и определять их относительное местоположение."</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Чтение всех уведомлений, в том числе сведений о контактах, сообщениях и фотографиях."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Трансляция приложений с телефона."</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index f23b8d6..0b9248b 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ඉඩ නොදෙන්න"</string>
<string name="consent_back" msgid="2560683030046918882">"ආපසු"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> the හි යෙදුම්වලට <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> හි අවසරම දෙන්නද?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>මෙයට මයික්රෆෝනය, කැමරාව සහ ස්ථාන ප්රවේශය සහ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> හි අනෙකුත් සංවේදී අවසර ඇතුළත් විය හැකිය.</p> <p>ඔබට ඔබගේ සැකසීම් තුළ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> හිදී ඕනෑම වේලාවක මෙම අවසර වෙනස් කළ හැකිය.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"මෙයට <strong>මයික්රොෆෝනය</strong>, <strong>කැමරාව</strong>, සහ <strong>ස්ථාන ප්රවේශය</strong>, සහ <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> මත අනෙකුත් සංවේදී අවසර ඇතුළත් විය හැක. <br/><br/>ඔබට <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> හි ඔබේ සැකසීම් තුළ ඕනෑම වේලාවක මෙම අවසර වෙනස් කළ හැක."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"යෙදුම් නිරූපකය"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"වැඩිදුර තොරතුරු බොත්තම"</string>
<string name="permission_phone" msgid="2661081078692784919">"දුරකථනය"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"සම්බන්ධතා"</string>
<string name="permission_calendar" msgid="6805668388691290395">"දිනදර්ශනය"</string>
<string name="permission_microphone" msgid="2152206421428732949">"මයික්රෆෝනය"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"ඇමතුම් ලොග"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"අවට උපාංග"</string>
<string name="permission_storage" msgid="6831099350839392343">"ඡායාරූප සහ මාධ්ය"</string>
<string name="permission_notification" msgid="693762568127741203">"දැනුම්දීම්"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"යෙදුම්"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"ආසන්න උපාංග ප්රවාහය"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"දුරකථන ඇමතුම් ගැනීමට සහ කළමනාකරණය කිරීමට හැක"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"දුරකථන ඇමතුම් ලොගය කියවීමට සහ ලිවීමට හැක"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS පණිවිඩ යැවීමට සහ බැලීමට හැක"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"ඔබේ සම්බන්ධතා වෙත ප්රවේශ විය හැක"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"ඔබේ දින දර්ශනයට ප්රවේශ විය හැක"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"මයික්රෆෝනය භාවිතයෙන් ශ්රව්ය පටිගත කළ හැක"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"අවට උපාංගවල සාපේක්ෂ පිහිටීම සොයා ගැනීමට, සම්බන්ධ කිරීමට, සහ තීරණය කිරීමට හැක"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"සම්බන්ධතා, පණිවිඩ සහ ඡායාරූප වැනි තොරතුරු ඇතුළුව සියලු දැනුම්දීම් කියවිය හැකිය"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"ඔබේ දුරකථනයේ යෙදුම් ප්රවාහ කරන්න"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 1ed177e..6be4e2c 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Nepovoliť"</string>
<string name="consent_back" msgid="2560683030046918882">"Späť"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Chcete udeliť aplikáciám v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> rovnaké povolenia ako v zariadení <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Môžu zahŕňať prístup k mikrofónu, kamere a polohe a ďalšie citlivé povolenia v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Tieto povolenia môžete kedykoľvek zmeniť v Nastaveniach v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Môžu zahŕňať prístup k <strong>mikrofónu</strong>, <strong>kamere</strong> a <strong>polohe</strong>, a ďalšie citlivé povolenia v zariadení <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Tieto povolenia môžete kedykoľvek zmeniť v nastaveniach zariadenia <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikácie"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Tlačidlo Ďalšie informácie"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefón"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakty"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendár"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofón"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Zoznam hovorov"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Zariadenia v okolí"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotky a médiá"</string>
<string name="permission_notification" msgid="693762568127741203">"Upozornenia"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikácie"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streamovať do zariad. v okolí"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Môže uskutočňovať a spravovať telefonické hovory"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Môže čítať zo zoznamu hovorov telefónu a zapisovať doň"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Môže odosielať a zobrazovať správy SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Má prístup k vašim kontaktom"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Má prístup k vášmu kalendáru"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Môže nahrávať zvuk pomocou mikrofónu"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Môže vyhľadávať zariadenia v okolí, určovať ich relatívnu pozíciu a pripájať sa k nim"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Môže čítať všetky upozornenia vrátane informácií, ako sú kontakty, správy a fotky"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streamovať aplikácie telefónu"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 40a8827..7d3d168 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ne dovoli"</string>
<string name="consent_back" msgid="2560683030046918882">"Nazaj"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Ali želite aplikacijam v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> odobriti enaka dovoljenja kot v napravi <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>To lahko vključuje dostop do mikrofona, fotoaparata in lokacije ter druga občutljiva dovoljenja v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ta dovoljenja lahko kadar koli spremenite v nastavitvah v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"To lahko vključuje <strong>dostop do mikrofona</strong>, <strong>fotoaparata</strong> in <strong>lokacije</strong> ter druga občutljiva dovoljenja v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ta dovoljenja lahko kadar koli spremenite v nastavitvah v napravi <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona aplikacije"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Gumb za več informacij"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Stiki"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Koledar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Dnevniki klicev"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Naprave v bližini"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografije in predstavnost"</string>
<string name="permission_notification" msgid="693762568127741203">"Obvestila"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacije"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Predvajanje v napravi v bližini"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Lahko opravlja in upravlja telefonske klice"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Lahko bere in zapisuje dnevnik klicev v telefonu"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Lahko pošilja in si ogleduje sporočila SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Lahko dostopa do stikov"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Lahko dostopa do koledarja"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Lahko uporablja mikrofon za snemanje zvoka."</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Lahko išče naprave v bližini, se povezuje z njimi in določa njihov relativni položaj"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Lahko bere vsa obvestila, vključno s podatki, kot so stiki, sporočila in fotografije."</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Pretočno predvajanje aplikacij telefona"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 2a65cb3..6ff4ce8 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Mos lejo"</string>
<string name="consent_back" msgid="2560683030046918882">"Pas"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"T\'i jepen aplikacioneve në <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> të njëjtat leje si në <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Kjo mund të përfshijë qasjen te \"Mikrofoni\", \"Kamera\", \"Vendndodhja\" dhe leje të tjera për informacione delikate në <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p&gtTi mund t\'i ndryshosh këto leje në çdo kohë te \"Cilësimet\" në <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Kjo mund të përfshijë qasjen te <strong>Mikrofoni</strong>, <strong>Kamera</strong>, dhe <strong>Vendndodhja</strong>, dhe leje të tjera për informacione delikate në <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ti mund t\'i ndryshosh këto leje në çdo kohë te \"Cilësimet\" në <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ikona e aplikacionit"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Butoni \"Më shumë informacione\""</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefoni"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktet"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalendari"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofoni"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Evidencat e telefonatave"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Pajisjet në afërsi"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotografitë dhe media"</string>
<string name="permission_notification" msgid="693762568127741203">"Njoftimet"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Aplikacionet"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Transmetim: Pajisjet në afërsi"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Mund të bëjë dhe të menaxhojë telefonatat"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Mund të lexojë dhe të shkruajë në evidencën e telefonatave"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Mund të dërgojë dhe të shikojë mesazhet SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Mund të ketë qasje te kontaktet e tua"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Mund të ketë qasje te kalendari"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Mund të regjistrojë audio duke përdorur mikrofonin"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Mund të gjejë, të lidhet dhe të përcaktojë pozicionin e përafërt të pajisjeve në afërsi"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Mund të lexojë të gjitha njoftimet, duke përfshirë informacione si kontaktet, mesazhet dhe fotografitë"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Transmeto aplikacionet e telefonit tënd"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index bca28ab..fe9e5f9a 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Не дозволи"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Апликцијама на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> дајете све дозволе као на уређају <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>То може да обухвата приступ микрофону, камери и локацији, као и другим осетљивим дозволама на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>У сваком тренутку можете да промените те дозволе у Подешавањима на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"То може да обухвата приступ <strong>микрофону</strong>, <strong>камери</strong>, и <strong>локацији</strong>, и друге осетљиве дозволе на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Можете да промените те дозволе у било ком тренутку у Подешавањима на уређају <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Икона апликације"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Дугме за више информација"</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Микрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Евиденције позива"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Уређаји у близини"</string>
<string name="permission_storage" msgid="6831099350839392343">"Слике и медији"</string>
<string name="permission_notification" msgid="693762568127741203">"Обавештења"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Апликације"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Стримовање, уређаји у близини"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Може да упућује телефонске позиве и управља њима"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може да чита и пише евиденцију позива на телефону"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Може да шаље и прегледа SMS поруке"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Може да приступа контактима"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Може да приступа календару"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Може да снима звук помоћу микрофона"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може да проналази и утврђује релативну позицију уређаја у близини, као и да се повезује са њима"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Може да чита сва обавештења, укључујући информације попут контаката, порука и слика"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Стримујте апликације на телефону"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index 20d6069..11f115d 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Tillåt inte"</string>
<string name="consent_back" msgid="2560683030046918882">"Tillbaka"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Vill du ge apparna på <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> samma behörigheter som de har på <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Det kan gälla behörighet till mikrofon, kamera och plats och åtkomstbehörighet till andra känsliga uppgifter på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Du kan när som helst ändra behörigheterna i inställningarna på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.lt;/p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Detta kan inkludera <strong>Mikrofon-</strong>, <strong>Kamera-</strong>, och <strong>Platsåtkomst</strong>, samt andra känsliga behörigheter på <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Du kan ändra dessa behörigheter när som helst i inställningarna på <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Appikon"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Knappen Mer information"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontakter"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalender"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Samtalsloggar"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Enheter i närheten"</string>
<string name="permission_storage" msgid="6831099350839392343">"Foton och media"</string>
<string name="permission_notification" msgid="693762568127741203">"Aviseringar"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Appar"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"En enhet i närheten streamar"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Får skapa och hantera telefonsamtal"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Får läsa och skriva samtalslogg"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Får skicka och visa sms"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Får åtkomst till dina kontakter"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Får åtkomst till din kalender"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Kan spela in ljud med mikrofonen"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Får hitta, ansluta till och avgöra den relativa positionen för enheter i närheten"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kan läsa alla aviseringar, inklusive information som kontakter, meddelanden och foton"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Streama telefonens appar"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 29c6a42..2c6bc8f 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Usiruhusu"</string>
<string name="consent_back" msgid="2560683030046918882">"Nyuma"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Ungependa kuzipa programu katika <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ruhusa ile ile kama kwenye <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Hii huenda ikajumuisha ufikiaji wa Maikrofoni, Kamera na Mahali, pamoja na ruhusa nyingine nyeti kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Unaweza kubadilisha ruhusa hizi muda wowote katika Mipangilio yako kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Hii ni pamoja na <strong>Maikrofoni</strong>, <strong>Kamera</strong>, na <strong>Uwezo wa kufikia mahali</strong>, na ruhusa nyingine nyeti kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Unaweza kubadilisha ruhusa hizi wakati wowote katika Mipangilio yako kwenye <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Aikoni ya Programu"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Kitufe cha Maelezo Zaidi"</string>
<string name="permission_phone" msgid="2661081078692784919">"Simu"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Anwani"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Kalenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Maikrofoni"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Rekodi za nambari za simu"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Vifaa vilivyo karibu"</string>
<string name="permission_storage" msgid="6831099350839392343">"Picha na maudhui"</string>
<string name="permission_notification" msgid="693762568127741203">"Arifa"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Programu"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Kutiririsha kwenye Kifaa kilicho Karibu"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Inaweza kupiga na kudhibiti simu"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Inaweza kusoma na kuandika rekodi ya nambari za simu"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Inaweza kutuma na kuangalia ujumbe wa SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Inaweza kufikia anwani zako"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Inaweza kufikia kalenda yako"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Inaweza kurekodi sauti ikitumia maikrofoni"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Inaweza kutafuta, kuunganisha na kubaini nafasi ya makadirio ya vifaa vilivyo karibu"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Inaweza kusoma arifa zote, ikiwa ni pamoja na maelezo kama vile anwani, ujumbe na picha"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Tiririsha programu za simu yako"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index 0658728..ac454ba 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"அனுமதிக்க வேண்டாம்"</string>
<string name="consent_back" msgid="2560683030046918882">"பின்செல்"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்தில் இருக்கும் அதே அனுமதிகளை <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> சாதனத்தில் உள்ள ஆப்ஸுக்கும் வழங்கவா?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p> சாதனத்தில் உள்ள மைக்ரோஃபோன், கேமரா, இருப்பிட அணுகல், பாதுகாக்கவேண்டிய பிற தகவல்கள் ஆகியவற்றுக்கான அனுமதிகள் இதிலடங்கும்.<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p> சாதனத்தில் உள்ள அமைப்புகளில் இந்த அனுமதிகளை எப்போது வேண்டுமானாலும் நீங்கள் மாற்றிக்கொள்ளலாம்."</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"<strong>மைக்ரோஃபோன்</strong>, <strong>கேமரா</strong>, <strong>இருப்பிட அணுகல்</strong>, ஆகியவற்றுக்கான அனுமதிகளும் <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> சாதனத்தில் உள்ள பிற பாதுகாக்கவேண்டிய தகவல்களுக்கான அனுமதிகளும் இதில் அடங்கக்கூடும். <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> <br/><br/>சாதனத்தில் உள்ள அமைப்புகளில் இந்த அனுமதிகளை எப்போது வேண்டுமானாலும் மாற்றிக்கொள்ளலாம்."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ஆப்ஸ் ஐகான்"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"கூடுதல் தகவல்கள் பட்டன்"</string>
<string name="permission_phone" msgid="2661081078692784919">"மொபைல்"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"தொடர்புகள்"</string>
<string name="permission_calendar" msgid="6805668388691290395">"கேலெண்டர்"</string>
<string name="permission_microphone" msgid="2152206421428732949">"மைக்ரோஃபோன்"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"அழைப்புப் பதிவுகள்"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"அருகிலுள்ள சாதனங்கள்"</string>
<string name="permission_storage" msgid="6831099350839392343">"படங்கள் மற்றும் மீடியா"</string>
<string name="permission_notification" msgid="693762568127741203">"அறிவிப்புகள்"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ஆப்ஸ்"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"அருகிலுள்ள சாதன ஸ்ட்ரீமிங்"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"மொபைல் அழைப்புகளைச் செய்யலாம் நிர்வகிக்கலாம்"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"மொபைல் அழைப்புப் பதிவைப் படிக்கலாம் எழுதலாம்"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"மெசேஜ்களை அனுப்பலாம் பார்க்கலாம்"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"உங்கள் தொடர்புகளை அணுகலாம்"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"உங்கள் கேலெண்டரை அணுகலாம்"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"மைக்ரோஃபோனைப் பயன்படுத்தி ஆடியோவை ரெக்கார்டு செய்யலாம்"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"அருகிலுள்ள சாதனங்களைக் கண்டறியலாம் அவற்றுடன் இணையலாம் அவற்றின் தூரத்தைத் தீர்மானிக்கலாம்"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"தொடர்புகள், மெசேஜ்கள், படங்கள் போன்ற தகவல்கள் உட்பட அனைத்து அறிவிப்புகளையும் படிக்க முடியும்"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"உங்கள் மொபைல் ஆப்ஸை ஸ்ட்ரீம் செய்யலாம்"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 8450507..cb0356c 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"అనుమతించవద్దు"</string>
<string name="consent_back" msgid="2560683030046918882">"వెనుకకు"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>లోని యాప్లకు <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>లో ఉన్న అనుమతులను ఇవ్వాలా?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p><strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>లో మైక్రోఫోన్, కెమెరా, లొకేషన్ యాక్సెస్, ఇంకా ఇతర గోప్యమైన సమాచార యాక్సెస్ అనుమతులు ఇందులో ఉండవచ్చు.</p> <p>మీరు <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>లో మీ సెట్టింగ్లలో ఎప్పుడైనా ఈ అనుమతులను మార్చవచ్చు.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"వీటిలో భాగంగా <strong>మైక్రోఫోన్</strong>, <strong>కెమెరా</strong>, ఇంకా <strong>లొకేషన్ యాక్సెస్</strong>, అలాగే <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>పై ఇతర గోప్యమైన సమాచార యాక్సెస్ అనుమతులు ఉండవచ్చు. <br/><br/>ఈ అనుమతులను మీరు <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>లోని మీ సెట్టింగ్లలో ఎప్పుడైనా మార్చవచ్చు."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"యాప్ చిహ్నం"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"మరింత సమాచారం బటన్"</string>
<string name="permission_phone" msgid="2661081078692784919">"ఫోన్"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"కాంటాక్ట్లు"</string>
<string name="permission_calendar" msgid="6805668388691290395">"క్యాలెండర్"</string>
<string name="permission_microphone" msgid="2152206421428732949">"మైక్రోఫోన్"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"కాల్ లాగ్లు"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"సమీపంలోని పరికరాలు"</string>
<string name="permission_storage" msgid="6831099350839392343">"ఫోటోలు, మీడియా"</string>
<string name="permission_notification" msgid="693762568127741203">"నోటిఫికేషన్లు"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"యాప్లు"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"సమీపంలోని పరికర స్ట్రీమింగ్"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"ఫోన్ కాల్స్ చేయగలదు, అలాగే మేనేజ్ చేయగలదు"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"ఫోన్ కాల్ లాగ్ను చదవగలదు, రాయగలదు"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS మెసేజ్లను పంపగలదు, అలాగే చూడగలదు"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"మీ కాంటాక్ట్లను యాక్సెస్ చేయగలదు"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"మీ క్యాలెండర్ను యాక్సెస్ చేయగలదు"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"మైక్రోఫోన్ను ఉపయోగించి ఆడియోను రికార్డ్ చేయవచ్చు"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"సమీపంలోని పరికరాలను కనుగొనగలదు, వాటికి కనెక్ట్ అవ్వగలదు, అవి ఎంత దూరంలో ఉన్నాయో తెలుసుకొనగలదు"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"కాంటాక్ట్లు, మెసేజ్లు, ఫోటోల వంటి సమాచారంతో సహా అన్ని నోటిఫికేషన్లను చదవగలదు"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"మీ ఫోన్లోని యాప్లను స్ట్రీమ్ చేయండి"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 5a51d4d..e42bec5 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"ไม่อนุญาต"</string>
<string name="consent_back" msgid="2560683030046918882">"กลับ"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ให้แอปใน <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> มีสิทธิ์เหมือนกับใน <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> ไหม"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>โดยอาจรวมถึงสิทธิ์เข้าถึงไมโครโฟน กล้อง และตำแหน่ง ตลอดจนสิทธิ์ที่มีความละเอียดอ่อนอื่นๆ ใน <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>คุณเปลี่ยนแปลงสิทธิ์เหล่านี้ได้ทุกเมื่อในการตั้งค่าใน <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"โดยอาจรวมถึงสิทธิ์เข้าถึง <strong>ไมโครโฟน</strong> <strong>กล้อง</strong> และ<strong>ตำแหน่ง</strong> ตลอดจนสิทธิ์ที่มีความละเอียดอ่อนอื่นๆ ใน <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> <br/><br/>คุณเปลี่ยนแปลงสิทธิ์เหล่านี้ได้ทุกเมื่อในการตั้งค่าบน <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ไอคอนแอป"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"ปุ่มข้อมูลเพิ่มเติม"</string>
<string name="permission_phone" msgid="2661081078692784919">"โทรศัพท์"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"รายชื่อติดต่อ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"ปฏิทิน"</string>
<string name="permission_microphone" msgid="2152206421428732949">"ไมโครโฟน"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"บันทึกการโทร"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"อุปกรณ์ที่อยู่ใกล้เคียง"</string>
<string name="permission_storage" msgid="6831099350839392343">"รูปภาพและสื่อ"</string>
<string name="permission_notification" msgid="693762568127741203">"การแจ้งเตือน"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"แอป"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"การสตรีมไปยังอุปกรณ์ที่อยู่ใกล้เคียง"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"สามารถโทรออกและจัดการการโทร"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"สามารถอ่านและเขียนบันทึกการโทรของโทรศัพท์"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"สามารถส่งและดูข้อความ SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"สามารถเข้าถึงรายชื่อติดต่อของคุณ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"สามารถเข้าถึงปฏิทินของคุณ"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"บันทึกเสียงโดยใช้ไมโครโฟนได้"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"สามารถค้นหา เชื่อมต่อ และระบุตำแหน่งซึ่งสัมพันธ์กับอุปกรณ์ที่อยู่ใกล้เคียง"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"สามารถอ่านการแจ้งเตือนทั้งหมด รวมถึงข้อมูลอย่างรายชื่อติดต่อ ข้อความ และรูปภาพ"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"สตรีมแอปของโทรศัพท์คุณ"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 7bdd81b..15b69a2 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Huwag payagan"</string>
<string name="consent_back" msgid="2560683030046918882">"Bumalik"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Bigyan ang mga app sa <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ng mga pahintulot na mayroon din sa <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Posibleng kabilang dito ang access sa Mikropono, Camera, at Lokasyon, at iba pang pahintulot sa sensitibong impormasyon sa <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Puwede mong baguhin ang mga pahintulot na ito anumang oras sa iyong Mga Setting sa <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Posibleng kasama rito ang <strong>access sa Mikropono</strong>, <strong>Camera</strong>, at <strong>Lokasyon</strong>, at iba pang pahintulot sa sensitibong impormasyon sa <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Puwede mong baguhin ang mga pahintulot na ito anumang oras sa iyong Mga Setting sa <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Icon ng App"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Button ng Dagdag Impormasyon"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telepono"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Mga Contact"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Calendar"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikropono"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Mga log ng tawag"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Mga kalapit na device"</string>
<string name="permission_storage" msgid="6831099350839392343">"Mga larawan at media"</string>
<string name="permission_notification" msgid="693762568127741203">"Mga Notification"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Mga App"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Streaming sa Kalapit na Device"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Puwedeng gumawa at mamahala ng mga tawag sa telepono"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Puwedeng magbasa at magsulat ng log ng tawag sa telepono"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Puwedeng magpadala at tumingin ng mga SMS message"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Puwedeng mag-access ng iyong mga contact"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Puwedeng mag-access ng iyong kalendaryo"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Puwedeng mag-record ng audio gamit ang mikropono"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Puwedeng mahanap ang, kumonekta sa, at tukuyin ang relatibong posisyon ng mga kalapit na device"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Magbasa ng lahat ng notification, kabilang ang impormasyon gaya ng mga contact, mensahe, at larawan"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"I-stream ang mga app ng iyong telepono"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 98ea47a..35b99a7 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"İzin verme"</string>
<string name="consent_back" msgid="2560683030046918882">"Geri"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> cihazındaki uygulamalara, <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> cihazındakiyle aynı izinler verilsin mi?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Mikrofon, kamera ve konum erişiminin yanı sıra <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındaki diğer hassas bilgilere erişim izinleri de bu kapsamda olabilir.</p> <p>Bu izinleri istediğiniz zaman <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazındaki Ayarlar bölümünden değiştirebilirsiniz.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Bu; <strong>Mikrofon</strong>, <strong>Kamera</strong> ve <strong>Konum erişimi</strong> izinlerinin yanı sıra <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> cihazındaki diğer hassas bilgilere erişim izinlerini içerebilir. <br/><br/><strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> cihazının Ayarlar bölümünden istediğiniz zaman bu izinleri değiştirebilirsiniz."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Uygulama Simgesi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Daha Fazla Bilgi Düğmesi"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kişiler"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Takvim"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Arama kayıtları"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Yakındaki cihazlar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Fotoğraflar ve medya"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirimler"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Uygulamalar"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Yakındaki Cihazda Oynatma"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon aramaları yapabilir ve telefon aramalarını yönetebilir"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon arama kaydını okuma ve yazma"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS mesajları gönderebilir ve görüntüleyebilir"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kişilerinize erişebilir"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Takviminize erişebilir"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Mikrofonu kullanarak ses kaydedebilir"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Yakındaki cihazları keşfedip bağlanabilir ve bu cihazların göreli konumunu belirleyebilir"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Kişiler, mesajlar ve fotoğraflar da dahil olmak üzere tüm bildirimleri okuyabilir"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefonunuzun uygulamalarını yayınlama"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 38c9ba2..d1d0815 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Не дозволяти"</string>
<string name="consent_back" msgid="2560683030046918882">"Назад"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Надати додаткам на пристрої <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> такі самі дозволи, що й на пристрої <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Це може бути доступ до мікрофона, камери та геоданих, а також до іншої конфіденційної інформації на пристрої <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ви можете будь-коли змінити ці дозволи в налаштуваннях на пристрої <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Це можуть бути дозволи <strong>Мікрофон</strong>, <strong>Камера</strong>, <strong>Геодані</strong>, а також інші дозволи на доступ до чутливих даних на пристрої <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ви можете будь-коли змінити ці дозволи в налаштуваннях на пристрої <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Значок додатка"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Кнопка \"Докладніше\""</string>
<string name="permission_phone" msgid="2661081078692784919">"Телефон"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Контакти"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Календар"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Мікрофон"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Журнали викликів"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Пристрої поблизу"</string>
<string name="permission_storage" msgid="6831099350839392343">"Фотографії та медіафайли"</string>
<string name="permission_notification" msgid="693762568127741203">"Сповіщення"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Додатки"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Трансляція на пристрої поблизу"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Може здійснювати телефонні виклики й керувати ними"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Може переглядати й редагувати журнал викликів телефона"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Може надсилати й переглядати SMS-повідомлення"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Має доступ до ваших контактів"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Має доступ до вашого календаря"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Може записувати звук за допомогою мікрофона"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Може знаходити пристрої поблизу, підключатися до них і визначати їх відносне розташування"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Може читати всі сповіщення, зокрема таку інформацію, як контакти, повідомлення та фотографії"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Транслювати додатки телефона"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index b68044e..7cd681c 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"اجازت نہ دیں"</string>
<string name="consent_back" msgid="2560683030046918882">"پیچھے"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"ایپس کو <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> پر وہی اجازتیں دیں جو <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> پر دی گئی ہیں؟"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>اس میں مائیکروفون، کیمرا اور مقام تک رسائی، اور <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> پر دیگر حساس اجازتیں شامل ہو سکتی ہیں۔</p><p>آپ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> پر کسی بھی وقت اپنی ترتیبات میں ان اجازتوں کو تبدیل کر سکتے ہیں۔</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"اس میں <strong>مائیکروفون</strong> ،<strong>کیمرا</strong> اور <strong>مقام تک رسائی</strong> اور <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> پر دیگر حساس اجازتیں شامل ہو سکتی ہیں۔ <br/><br/>آپ <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> پر کسی بھی وقت اپنی ترتیبات میں ان اجازتوں کو تبدیل کر سکتے ہیں۔"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"ایپ کا آئیکن"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"مزید معلومات کا بٹن"</string>
<string name="permission_phone" msgid="2661081078692784919">"فون"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"رابطے"</string>
<string name="permission_calendar" msgid="6805668388691290395">"کیلنڈر"</string>
<string name="permission_microphone" msgid="2152206421428732949">"مائیکروفون"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"کال لاگز"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"قریبی آلات"</string>
<string name="permission_storage" msgid="6831099350839392343">"تصاویر اور میڈیا"</string>
<string name="permission_notification" msgid="693762568127741203">"اطلاعات"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"ایپس"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"قریبی آلات کی سلسلہ بندی"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"فون کالز کر سکتا ہے اور ان کا نظم کر سکتا ہے"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"فون کال لاگ پڑھ کر لکھ سکتا ہے"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS پیغامات بھیج اور دیکھ سکتا ہے"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"آپ کے رابطوں تک رسائی حاصل کر سکتا ہے"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"آپ کے کیلنڈر تک رسائی حاصل کر سکتا ہے"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"مائیکروفون کا استعمال کر کے آڈیو ریکارڈ کر سکتے ہیں"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"قریبی آلات کی متعلقہ پوزیشن تلاش کر سکتا ہے، ان سے منسلک ہو سکتا ہے اور اس کا تعین کر سکتا ہے"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"رابطوں، پیغامات اور تصاویر جیسی معلومات سمیت تمام اطلاعات پڑھ سکتے ہیں"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"اپنے فون کی ایپس کی سلسلہ بندی کریں"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 514f4bf..4a6de17 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ruxsat berilmasin"</string>
<string name="consent_back" msgid="2560683030046918882">"Orqaga"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> ilovalariga <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> qurilmasidagi kabi bir xil ruxsatlar berilsinmi?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Bunga <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> qurilmasidagi Mikrofon, Kamera, Joylashuv kabi muhim ruxsatlar kirishi mumkin.</p> <p>Bu ruxsatlarni istalgan vaqt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> Sozlamalari orqali oʻzgartirish mumkin.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Ilovada <strong>,ikrofon</strong>, <strong>kamera</strong>, <strong>joylashuv axboroti</strong>, va <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g> qurilmasidagi boshqa shaxsiy maʼlumotlarga kirish imkoni paydo boʻladi</strong>. <br/><br/>Bu ruxsatlarni istalgan vaqt <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g> sozlamalari orqali oʻzgartirish mumkin</strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Ilova belgisi"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Batafsil axborot tugmasi"</string>
<string name="permission_phone" msgid="2661081078692784919">"Telefon"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Kontaktlar"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Taqvim"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Mikrofon"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Chaqiruvlar jurnali"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Atrofdagi qurilmalar"</string>
<string name="permission_storage" msgid="6831099350839392343">"Suratlar va media"</string>
<string name="permission_notification" msgid="693762568127741203">"Bildirishnomalar"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Ilovalar"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Atrofdagi qurilmalarga uzatish"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Telefon chaqiruvlarini bajarishi va boshqarishi mumkin"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Telefon chaqiruvlari jurnalini koʻrishi va oʻzgartirishi mumkin"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"SMS xabarlarni koʻrishi va yuborishi mumkin"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Kontaktlarga ruxsati bor"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Taqvimga ruxsati bor"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Mikrofon orqali audio yozib olishi mumkin"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Atrofdagi qurilmalarni qidirishi, joylashuvini aniqlashi va ularga ulanishi mumkin"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Barcha bildirishnomalarni, jumladan, kontaktlar, xabarlar va suratlarni oʻqishi mumkin"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Telefondagi ilovalarni translatsiya qilish"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 05596e1..62f613b 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Không cho phép"</string>
<string name="consent_back" msgid="2560683030046918882">"Quay lại"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Cấp cho các ứng dụng trên <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> các quyền giống như trên <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Những quyền này có thể bao gồm quyền truy cập vào micrô, máy ảnh và thông tin vị trí, cũng như các quyền truy cập thông tin nhạy cảm khác trên <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Bạn có thể thay đổi những quyền này bất cứ lúc nào trong phần Cài đặt trên <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Những quyền này có thể bao gồm quyền truy cập vào <strong>Micrô</strong>, <strong>Máy ảnh</strong>, và <strong>Thông tin vị trí</strong>, cũng như các quyền truy cập thông tin nhạy cảm khác trên <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Bạn có thể thay đổi những quyền này bất cứ lúc nào trong phần Cài đặt trên <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Biểu tượng ứng dụng"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Nút thông tin khác"</string>
<string name="permission_phone" msgid="2661081078692784919">"Điện thoại"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Danh bạ"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Lịch"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Micrô"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Nhật ký cuộc gọi"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Thiết bị ở gần"</string>
<string name="permission_storage" msgid="6831099350839392343">"Ảnh và nội dung nghe nhìn"</string>
<string name="permission_notification" msgid="693762568127741203">"Thông báo"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Ứng dụng"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Truyền đến thiết bị ở gần"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Có thể thực hiện và quản lý các cuộc gọi điện thoại"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Có thể đọc và ghi nhật ký cuộc gọi điện thoại"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Có thể gửi và xem tin nhắn SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Có thể truy cập danh bạ"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Có thể truy cập lịch"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Có thể ghi âm bằng micrô"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Có thể tìm, kết nối và xác định vị trí tương đối của các thiết bị ở gần"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Có thể đọc tất cả các thông báo, kể cả những thông tin như danh bạ, tin nhắn và ảnh"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Truyền các ứng dụng trên điện thoại của bạn"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index 275b9a0..b6fa7fc 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"不允许"</string>
<string name="consent_back" msgid="2560683030046918882">"返回"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"要让<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong>上的应用享有在<strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>上的同等权限吗?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>这可能包括<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>的麦克风、摄像头和位置信息访问权限,以及其他敏感权限。</p> <p>您可以随时在<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>的“设置”中更改这些权限。</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"这可能包括<strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>的<strong>麦克风</strong>、<strong>摄像头</strong>和<strong>位置信息访问权限</strong>以及其他敏感权限。<br/><br/>您随时可以在<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>的“设置”中更改这些权限。"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"应用图标"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"更多信息按钮"</string>
<string name="permission_phone" msgid="2661081078692784919">"手机"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"通讯录"</string>
<string name="permission_calendar" msgid="6805668388691290395">"日历"</string>
<string name="permission_microphone" msgid="2152206421428732949">"麦克风"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"通话记录权限"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"附近的设备"</string>
<string name="permission_storage" msgid="6831099350839392343">"照片和媒体内容"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"应用"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"附近的设备流式传输"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"可以打电话及管理通话"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"可以读取和写入手机通话记录"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"可以发送和查看短信"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"可以访问您的通讯录"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"可以访问您的日历"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"可使用麦克风录音"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可以查找、连接附近的设备以及确定附近设备的相对位置"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"可以读取所有通知,包括合同、消息和照片等信息"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"流式传输手机上的应用"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 70d988b..7ab2992 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
<string name="consent_back" msgid="2560683030046918882">"返回"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"<strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> 上的應用程式可獲在 <strong><xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong> 上的相同權限嗎?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> 的麥克風、相機、位置和其他敏感資料的存取權。</p><p>您隨時可在 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> 的設定中變更這些權限。</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"這可能包括 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> 的<strong>麥克風</strong>、<strong>相機</strong>和<strong>位置資訊存取權</strong>以及其他敏感資料權限。<br/><br/>您隨時可透過 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> 的「設定」變更這些權限。"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"應用程式圖示"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"「更多資料」按鈕"</string>
<string name="permission_phone" msgid="2661081078692784919">"手機"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"通訊錄"</string>
<string name="permission_calendar" msgid="6805668388691290395">"日曆"</string>
<string name="permission_microphone" msgid="2152206421428732949">"麥克風"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"通話記錄"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"附近的裝置"</string>
<string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"附近的裝置串流"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"可撥打及管理通話"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"可讀取及寫入通話記錄"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"可傳送及查看簡訊"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"可存取聯絡人"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"可存取日曆"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"可使用麥克風錄音"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連線及判斷鄰近裝置的相對位置"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"可以讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"串流播放手機應用程式內容"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index c18a9f1..48c289c 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"不允許"</string>
<string name="consent_back" msgid="2560683030046918882">"返回"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"要讓「<xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g>」<strong></strong>的應用程式沿用在「<xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g>」<strong></strong>上的權限嗎?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>這可能包括「<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g>」<strong></strong>的麥克風、相機和位置資訊存取權和其他機密權限。</p> <p>你隨時可透過「<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g>」<strong></strong>的設定變更這些權限。</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"這可能包括 <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong> 的<strong>麥克風</strong>、<strong>相機</strong>和<strong>位置資訊存取權</strong>以及機密權限。<br/><br/>你隨時可透過 <strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong> 的「設定」變更這些權限。"</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"應用程式圖示"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"更多資訊按鈕"</string>
<string name="permission_phone" msgid="2661081078692784919">"電話"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"聯絡人"</string>
<string name="permission_calendar" msgid="6805668388691290395">"日曆"</string>
<string name="permission_microphone" msgid="2152206421428732949">"麥克風"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"通話記錄"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"鄰近裝置"</string>
<string name="permission_storage" msgid="6831099350839392343">"相片和媒體"</string>
<string name="permission_notification" msgid="693762568127741203">"通知"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"應用程式"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"鄰近裝置串流"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"可撥打及管理通話"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"可讀取及寫入通話記錄"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"可傳送及查看簡訊"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"可存取聯絡人"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"可存取日曆"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"可使用麥克風錄音"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"可尋找、連線及判斷鄰近裝置的相對位置"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"可讀取所有通知,包括聯絡人、訊息和電話等資訊"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"串流傳輸手機應用程式內容"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index 9dba977..f81406e 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -43,7 +43,7 @@
<string name="consent_no" msgid="2640796915611404382">"Ungavumeli"</string>
<string name="consent_back" msgid="2560683030046918882">"Emuva"</string>
<string name="permission_sync_confirmation_title" msgid="4409622174437248702">"Nikeza ama-app <strong><xliff:g id="COMPANION_DEVICE_NAME">%1$s</xliff:g></strong> izimvume ezifanayot <strong>njengaku-<xliff:g id="PRIMARY_DEVICE_NAME">%2$s</xliff:g></strong>?"</string>
- <string name="permission_sync_summary" msgid="4866838188678457084">"<p>Lokhu kungase kuhlanganisa Imakrofoni, Ikhamera, kanye Nokufinyelela kwendawo, kanye nezinye izimvume ezibucayi <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>.</p> <p>Ungashintsha lezi zimvume nganoma yisiphi isikhathi Kumasethingi akho <strong>ku-<xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>.</p>"</string>
+ <string name="permission_sync_summary" msgid="765497944331294275">"Lokhu kungahilela <strong>Imakrofoni</strong>, <strong>Ikhamera</strong>, kanye <strong>Nokufinyelelwa kwendawo</strong>, nezinye izimvume ezizwelayo <strong><xliff:g id="COMPANION_DEVICE_NAME_0">%1$s</xliff:g></strong>. <br/><br/>Ungakwazi ukushintsha lezi zimvume noma nini Kumasethingi akho ku-<strong><xliff:g id="COMPANION_DEVICE_NAME_1">%1$s</xliff:g></strong>."</string>
<string name="vendor_icon_description" msgid="4445875290032225965">"Isithonjana Se-app"</string>
<string name="vendor_header_button_description" msgid="6566660389500630608">"Inkinobho Yolwazi Olwengeziwe"</string>
<string name="permission_phone" msgid="2661081078692784919">"Ifoni"</string>
@@ -51,26 +51,19 @@
<string name="permission_contacts" msgid="3858319347208004438">"Oxhumana nabo"</string>
<string name="permission_calendar" msgid="6805668388691290395">"Ikhalenda"</string>
<string name="permission_microphone" msgid="2152206421428732949">"Imakrofoni"</string>
- <!-- no translation found for permission_call_logs (5546761417694586041) -->
- <skip />
+ <string name="permission_call_logs" msgid="5546761417694586041">"Amarekhodi wamakholi"</string>
<string name="permission_nearby_devices" msgid="7530973297737123481">"Amadivayisi aseduze"</string>
<string name="permission_storage" msgid="6831099350839392343">"Izithombe nemidiya"</string>
<string name="permission_notification" msgid="693762568127741203">"Izaziso"</string>
<string name="permission_app_streaming" msgid="6009695219091526422">"Ama-app"</string>
<string name="permission_nearby_device_streaming" msgid="5868108148065023161">"Ukusakazwa Kwedivayisi Eseduze"</string>
- <!-- no translation found for permission_phone_summary (6684396967861278044) -->
- <skip />
- <!-- no translation found for permission_call_logs_summary (6186103394658755022) -->
- <skip />
- <!-- no translation found for permission_sms_summary (3508442683678912017) -->
- <skip />
- <!-- no translation found for permission_contacts_summary (675861979475628708) -->
- <skip />
- <!-- no translation found for permission_calendar_summary (6460000922511766226) -->
- <skip />
+ <string name="permission_phone_summary" msgid="6684396967861278044">"Ingenza futhi iphathe amakholi wefoni"</string>
+ <string name="permission_call_logs_summary" msgid="6186103394658755022">"Ingafunda futhi ibhale irekhodi lamakholi efoni"</string>
+ <string name="permission_sms_summary" msgid="3508442683678912017">"Ingathumela futhi ibuke imiyalezo ye-SMS"</string>
+ <string name="permission_contacts_summary" msgid="675861979475628708">"Ingakwazi ukufinyelela oxhumana nabo"</string>
+ <string name="permission_calendar_summary" msgid="6460000922511766226">"Ingakwazi ukufinyelela ikhalenda lakho"</string>
<string name="permission_microphone_summary" msgid="4241354865859396558">"Ingakwazi ukurekhoda umsindo isebenzisa imakrofoni"</string>
- <!-- no translation found for permission_nearby_devices_summary (931940524460876655) -->
- <skip />
+ <string name="permission_nearby_devices_summary" msgid="931940524460876655">"Ingathola, ixhume, futhi inqume indawo ehlobene yamadivayisi aseduze"</string>
<string name="permission_notification_summary" msgid="884075314530071011">"Ingafunda zonke izaziso, okubandakanya ulwazi olufana noxhumana nabo, imilayezo, nezithombe"</string>
<string name="permission_app_streaming_summary" msgid="606923325679670624">"Sakaza ama-app wefoni yakho"</string>
<string name="permission_storage_summary" msgid="3918240895519506417"></string>
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index 674168a..6d225c3 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Kanselleer"</string>
<string name="string_continue" msgid="1346732695941131882">"Gaan voort"</string>
<string name="string_more_options" msgid="7990658711962795124">"Meer opsies"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Skep op ’n ander plek"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Stoor in ’n ander plek"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Gebruik ’n ander toestel"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Stoor op ’n ander toestel"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Veiliger met wagwoordsleutels"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Met wagwoordsleutels hoef jy nie komplekse wagwoorde te skep of te onthou nie"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Wagwoordsleutels is geënkripteerde digitale sleutels wat jy met jou vingerafdruk, gesig of skermslot skep"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Hulle word in ’n wagwoordbestuurder gestoor sodat jy op ander toestelle kan aanmeld"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Kies waar om <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"skep jou wagwoordsleutels"</string>
- <string name="save_your_password" msgid="6597736507991704307">"stoor jou wagwoord"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"stoor jou aanmeldinligting"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Kies ’n wagwoordbestuurder om jou inligting te stoor en volgende keer vinniger aan te meld."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Kies waar om jou <xliff:g id="CREATETYPES">%1$s</xliff:g> te stoor"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Kies ’n wagwoordbestuurder om jou inligting te stoor en volgende keer vinniger aan te meld"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Skep wagwoordsleutel vir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Stoor wagwoord vir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Stoor aanmeldinligting vir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Jy kan jou <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> op enige toestel gebruik. Dit is in <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> gestoor vir <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"wagwoordsleutel"</string>
<string name="password" msgid="6738570945182936667">"wagwoord"</string>
+ <string name="passkeys" msgid="5733880786866559847">"wagwoordsleutels"</string>
+ <string name="passwords" msgid="5419394230391253816">"wagwoorde"</string>
<string name="sign_ins" msgid="4710739369149469208">"aanmeldings"</string>
<string name="sign_in_info" msgid="2627704710674232328">"aanmeldinligting"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Stoor <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> in"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Skep ’n wagwoordsleutel op ’n ander toestel?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Skep wagwoordsleutel op ’n ander toestel?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Gebruik <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> vir al jou aanmeldings?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Hierdie wagwoordbestuurder sal jou wagwoorde en wagwoordsleutels berg om jou te help om maklik aan te meld."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Hierdie wagwoordbestuurder sal jou wagwoorde en wagwoordsleutels berg om jou te help om maklik aan te meld"</string>
<string name="set_as_default" msgid="4415328591568654603">"Stel as verstek"</string>
<string name="use_once" msgid="9027366575315399714">"Gebruik een keer"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> wagwoorde • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> wagwoordsleutels"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 2c4f402..8c52cf3 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ይቅር"</string>
<string name="string_continue" msgid="1346732695941131882">"ቀጥል"</string>
<string name="string_more_options" msgid="7990658711962795124">"ተጨማሪ አማራጮች"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"በሌላ ቦታ ውስጥ ይፍጠሩ"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ወደ ሌላ ቦታ ያስቀምጡ"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ሌላ መሣሪያ ይጠቀሙ"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ወደ ሌላ መሣሪያ ያስቀምጡ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"በይለፍ ቃል ይበልጥ ደህንነቱ የተጠበቀ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"በይለፍ ቁልፎች ውስብስብ የይለፍ ቁልፎችን መፍጠር ወይም ማስታወስ አያስፈልግዎትም"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"የይለፍ ቁልፎች የእርስዎን የጣት አሻራ፣ መልክ ወይም የማያ ገጽ መቆለፊያ በመጠቀም የሚፈጥሯቸው የተመሰጠሩ ዲጂታል ቆልፎች ናቸው"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"በሌሎች መሣሪያዎች ላይ መግባት እንዲችሉ በሚስጥር ቁልፍ አስተዳዳሪ ላይ ይቀመጣሉ"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"የት <xliff:g id="CREATETYPES">%1$s</xliff:g> እንደሚሆን ይምረጡ"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"የይለፍ ቁልፎችዎን ይፍጠሩ"</string>
- <string name="save_your_password" msgid="6597736507991704307">"የይለፍ ቃልዎን ያስቀምጡ"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"የመግቢያ መረጃዎን ያስቀምጡ"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"መረጃዎን ለማስቀመጥ እና በሚቀጥለው ጊዜ በፍጥነት ለመግባት የሚስጥር ቁልፍ አስተዳዳሪን ይጠቀሙ።"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ለ<xliff:g id="APPNAME">%1$s</xliff:g> የይለፍ ቁልፍ ይፈጠር?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"ለ<xliff:g id="APPNAME">%1$s</xliff:g> የይለፍ ቃል ይቀመጥ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"ለ<xliff:g id="APPNAME">%1$s</xliff:g> የመግቢያ መረጃ ይቀመጥ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"የእርስዎን <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> በማንኛውም መሣሪያ ላይ መጠቀም ይችላሉ። ለ<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> ወደ <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ተቀምጧል።"</string>
<string name="passkey" msgid="632353688396759522">"የይለፍ ቁልፍ"</string>
<string name="password" msgid="6738570945182936667">"የይለፍ ቃል"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"በሌላ መሣሪያ የይለፍ ቁልፍ ይፈጠር?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ለሁሉም መግቢያዎችዎ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ን ይጠቀሙ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ይህ የይለፍ ቃል አስተዳዳሪ በቀላሉ እንዲገቡ ለማገዝ የእርስዎን የይለፍ ቃሎች እና የይለፍ ቁልፎች ያከማቻል።"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"እንደ ነባሪ ያዋቅሩ"</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>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index c0ff69d..6b90817 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"إلغاء"</string>
<string name="string_continue" msgid="1346732695941131882">"متابعة"</string>
<string name="string_more_options" msgid="7990658711962795124">"خيارات إضافية"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"الإنشاء في مكان آخر"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"الحفظ في مكان آخر"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"استخدام جهاز آخر"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"الحفظ على جهاز آخر"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"توفير المزيد من الأمان باستخدام مفاتيح المرور"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"باستخدام مفاتيح المرور، لا حاجة لإنشاء كلمات مرور معقدة أو تذكّرها."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"مفاتيح المرور هي مفاتيح رقمية مشفّرة يمكنك إنشاؤها باستخدام بصمة الإصبع أو التعرّف على الوجه أو قفل الشاشة."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"يتم حفظها في مدير كلمات مرور، حتى تتمكن من تسجيل الدخول على أجهزة أخرى."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"اختيار مكان <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"إنشاء مفاتيح مرورك"</string>
- <string name="save_your_password" msgid="6597736507991704307">"حفظ كلمة المرور"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"حفظ معلومات تسجيل الدخول"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"اختَر مدير كلمة مرور لحفظ معلوماتك وتسجيل الدخول بشكل أسرع في المرة القادمة."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"إنشاء مفتاح مرور لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"هل تريد حفظ كلمة المرور لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\"؟"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"هل تريد حفظ معلومات تسجيل الدخول لتطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\"؟"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"يمكنك استخدام <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> لتطبيق \"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>\" على أي جهاز. يتم حفظه في \"<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>\" للحساب \"<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>\"."</string>
<string name="passkey" msgid="632353688396759522">"مفتاح مرور"</string>
<string name="password" msgid="6738570945182936667">"كلمة المرور"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"هل تريد إنشاء مفتاح مرور في جهاز آخر؟"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"هل تريد استخدام \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\" لكل عمليات تسجيل الدخول؟"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ستخزِّن خدمة إدارة كلمات المرور هذه كلمات المرور ومفاتيح المرور لمساعدتك في تسجيل الدخول بسهولة."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ضبط الخيار كتلقائي"</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>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 2c420fc..3a92b68 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"বাতিল কৰক"</string>
<string name="string_continue" msgid="1346732695941131882">"অব্যাহত ৰাখক"</string>
<string name="string_more_options" msgid="7990658711962795124">"অধিক বিকল্প"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"অন্য ঠাইত সৃষ্টি কৰক"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"অন্য ঠাইত ছেভ কৰক"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"অন্য ডিভাইচ ব্যৱহাৰ কৰক"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"অন্য এটা ডিভাইচত ছেভ কৰক"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"পাছকীৰ জৰিয়তে অধিক সুৰক্ষিত"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"পাছকী ব্যৱহাৰ কৰিলে আপুনি জটিল পাছৱৰ্ড সৃষ্টি কৰিব অথবা মনত ৰাখিব নালাগে"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"পাছকীসমূহ হৈছে আপুনি আপোনাৰ ফিংগাৰপ্ৰিণ্ট, মুখাৱয়ব অথবা স্ক্ৰীন লক ব্যৱহাৰ কৰি সৃষ্টি কৰা এনক্ৰিপ্ট কৰা ডিজিটেল চাবি"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"সেইসমূহ এটা পাছৱৰ্ড পৰিচালকত ছেভ কৰা হয়, যাতে আপুনি অন্য ডিভাইচসমূহত ছাইন ইন কৰিব পাৰে"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"ক’ত <xliff:g id="CREATETYPES">%1$s</xliff:g> সেয়া বাছনি কৰক"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"আপোনাৰ পাছকী সৃষ্টি কৰক"</string>
- <string name="save_your_password" msgid="6597736507991704307">"আপোনাৰ পাছৱৰ্ড ছেভ কৰক"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"আপোনাৰ ছাইন ইন কৰাৰ তথ্য ছেভ কৰক"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"আপোনাৰ তথ্য ছেভ কৰি পৰৱৰ্তী সময়ত দ্ৰুতভাৱে ছাইন ইন কৰিবলৈ এটা পাছৱৰ্ড পৰিচালক বাছনি কৰক।"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>ৰ বাবে পাছকী সৃষ্টি কৰিবনে?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g>ৰ বাবে পাছৱৰ্ড ছেভ কৰিবনে?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g>ৰ বাবে ছাইন ইনৰ তথ্য ছেভ কৰিবনে?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"আপুনি আপোনাৰ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> যিকোনো ডিভাইচত ব্যৱহাৰ কৰিব পাৰে। এইটো <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>ৰ বাবে <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>ত ছেভ কৰা হৈছে।"</string>
<string name="passkey" msgid="632353688396759522">"পাছকী"</string>
<string name="password" msgid="6738570945182936667">"পাছৱৰ্ড"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"অন্য এটা ডিভাইচত এটা পাছকী সৃষ্টি কৰিবনে?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"আপোনাৰ আটাইবোৰ ছাইন ইনৰ বাবে <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ব্যৱহাৰ কৰিবনে?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"আপোনাক সহজে ছাইন ইন কৰাত সহায় কৰিবলৈ এই পাছৱৰ্ড পৰিচালকটোৱে আপোনাৰ পাছৱৰ্ড আৰু পাছকী ষ্ট’ৰ কৰিব।"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ডিফ’ল্ট হিচাপে ছেট কৰক"</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>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 982562a..d7f3025 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Ləğv edin"</string>
<string name="string_continue" msgid="1346732695941131882">"Davam edin"</string>
<string name="string_more_options" msgid="7990658711962795124">"Digər seçimlər"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Başqa yerdə yaradın"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Başqa yerdə yadda saxlayın"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Digər cihaz istifadə edin"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Başqa cihazda yadda saxlayın"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Giriş açarları ilə daha təhlükəsiz"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Giriş açarları ilə mürəkkəb parollar yaratmağa və ya yadda saxlamağa ehtiyac yoxdur"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Giriş açarları barmaq izi, üz və ya ekran kilidindən istifadə edərək yaratdığınız şifrələnmiş rəqəmsal açarlardır"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Onlar parol menecerində saxlanılır ki, digər cihazlarda daxil ola biləsiniz"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> üçün yer seçin"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"giriş açarları yaradın"</string>
- <string name="save_your_password" msgid="6597736507991704307">"parolunuzu yadda saxlayın"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"giriş məlumatınızı yadda saxlayın"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Məlumatlarınızı yadda saxlamaq və növbəti dəfə daha sürətli daxil olmaq üçün parol meneceri seçin."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün giriş açarı yaradılsın?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün parol yadda saxlanılsın?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> üçün giriş məlumatları yadda saxlansın?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> domenini istənilən cihazda istifadə edə bilərsiniz. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> üçün <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> xidmətində saxlanılıb."</string>
<string name="passkey" msgid="632353688396759522">"giriş açarı"</string>
<string name="password" msgid="6738570945182936667">"parol"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"girişlər"</string>
<string name="sign_in_info" msgid="2627704710674232328">"Giriş məlumatları"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> burada yadda saxlansın:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Başqa cihazda giriş açarı yaradılsın?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Bütün girişlər üçün <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> istifadə edilsin?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Bu parol meneceri asanlıqla daxil olmanıza kömək etmək üçün parollarınızı və giriş açarlarınızı saxlayacaq."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Defolt olaraq seçin"</string>
<string name="use_once" msgid="9027366575315399714">"Bir dəfə istifadə edin"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> giriş açarı"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index 2a63a9e..6e8ec71 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Otkaži"</string>
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
<string name="string_more_options" msgid="7990658711962795124">"Još opcija"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Napravi na drugom mestu"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Sačuvaj na drugom mestu"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Koristi drugi uređaj"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Sačuvaj na drugi uređaj"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Bezbednije uz pristupne kodove"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne kodove nema potrebe da pravite ili pamtite složene lozinke"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni kodovi su šifrovani digitalni kodovi koje pravite pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Čuvaju se u menadžeru lozinki da biste mogli da se prijavljujete na drugim uređajima"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Odaberite lokaciju za: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"napravite pristupne kodove"</string>
- <string name="save_your_password" msgid="6597736507991704307">"sačuvajte lozinku"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"sačuvajte podatke o prijavljivanju"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Izaberite menadžera lozinki da biste sačuvali podatke i brže se prijavili sledeći put."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Želite da napravite pristupni kôd za: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Želite da sačuvate lozinku za: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Želite da sačuvate podatke za prijavljivanje za: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Možete da koristite tip domena <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> na bilo kom uređaju. Čuva se kod korisnika <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> za: <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"pristupni kôd"</string>
<string name="password" msgid="6738570945182936667">"lozinka"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"prijavljivanja"</string>
<string name="sign_in_info" msgid="2627704710674232328">"podaci za prijavljivanje"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvajte stavku<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Želite da napravite pristupni kôd na drugom uređaju?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite da za sva prijavljivanja koristite: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ovaj menadžer lozinki će čuvati lozinke i pristupne kodove da biste se lako prijavljivali."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Podesi kao podrazumevano"</string>
<string name="use_once" msgid="9027366575315399714">"Koristi jednom"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Lozinki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Pristupnih kodova:<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index 091527a..99af511 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Скасаваць"</string>
<string name="string_continue" msgid="1346732695941131882">"Далей"</string>
<string name="string_more_options" msgid="7990658711962795124">"Дадатковыя параметры"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Стварыць у іншым месцы"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Захаваць у іншым месцы"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Скарыстаць іншую прыладу"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Захаваць на іншую прыладу"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"З ключамі доступу вам будзе бяспечней."</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Дзякуючы ключам доступу вам не трэба ствараць і запамінаць складаныя паролі."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключы доступу – гэта зашыфраваныя лючбавыя ключы, створаныя вамі з дапамогай адбітка пальца, твару ці блакіроўкі экрана."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Яны захаваны ў менеджары пароляў. Дзякуючы гэтаму вы можаце ўваходзіць на іншых прыладах"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Выберыце, дзе <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"стварыць ключы доступу"</string>
- <string name="save_your_password" msgid="6597736507991704307">"захаваць пароль"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"захаваць інфармацыю пра спосаб уваходу"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Выберыце менеджар пароляў, каб захаваць свае даныя і забяспечыць хуткі ўваход у наступныя разы."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Стварыце ключ доступу да праграмы \"<xliff:g id="APPNAME">%1$s</xliff:g>\""</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Захаваць пароль для праграмы \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Захаваць інфармацыю пра спосаб уваходу ў праграму \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Вы можаце выкарыстоўваць <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g><xliff:g id="APPDOMAINNAME">%1$s</xliff:g> на любой прыладзе. Даныя для \"<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>\" захоўваюцца ў папку \"<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>\"."</string>
<string name="passkey" msgid="632353688396759522">"ключ доступу"</string>
<string name="password" msgid="6738570945182936667">"пароль"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Стварыць ключ доступу на іншай прыладзе?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Выкарыстоўваць папку \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\" для ўсіх спосабаў уваходу?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Каб вам было прасцей уваходзіць у сістэму, вашы паролі і ключы доступу будуць захоўвацца ў менеджары пароляў."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Выкарыстоўваць стандартна"</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>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 65ef0df2..13ebe24 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Отказ"</string>
<string name="string_continue" msgid="1346732695941131882">"Напред"</string>
<string name="string_more_options" msgid="7990658711962795124">"Още опции"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Създаване другаде"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Запазване на друго място"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Използване на друго устройство"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Запазване на друго устройство"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"По-сигурно с помощта на кодове за достъп"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Когато използвате кодове за достъп, не е необходимо да създавате, нито да помните сложни пароли"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кодовете за достъп са шифровани дигитални ключове, които създавате посредством отпечатъка, лицето си или опцията си за заключване на екрана"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Данните се запазват в мениджър на пароли, за да можете да влизате в профила си на други устройства"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Изберете място за <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"създаване на кодовете ви за достъп"</string>
- <string name="save_your_password" msgid="6597736507991704307">"запазване на паролата ви"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"запазване на данните ви за вход"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Изберете мениджър на пароли, в който да се запазят данните ви, така че следващия път да влезете по-бързо в профила си."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Да се създаде ли код за достъп за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Да се запази ли паролата за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Да се запазят ли данните за вход за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Можете да използвате <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> за <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> на всяко устройство. Тези данни се запазват в(ъв) <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> за <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"код за достъп"</string>
<string name="password" msgid="6738570945182936667">"парола"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Да се създаде ли код за достъп на друго устройство?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Да се използва ли <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> за всичките ви данни за вход?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Този мениджър на пароли ще съхранява вашите пароли и кодове за достъп, за да влизате лесно в профила си."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Задаване като основно"</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>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index a6cd1b3..a19fe71 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"বাতিল করুন"</string>
<string name="string_continue" msgid="1346732695941131882">"চালিয়ে যান"</string>
<string name="string_more_options" msgid="7990658711962795124">"আরও বিকল্প"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"অন্য জায়গায় তৈরি করুন"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"অন্য জায়গায় সেভ করুন"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"অন্য ডিভাইস ব্যবহার করুন"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"অন্য ডিভাইসে সেভ করুন"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"\'পাসকী\'-এর সাথে সুরক্ষিত"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"\'পাসকী\' ব্যবহার করলে জটিল পাসওয়ার্ড তৈরি করার বা মনে রাখার কোনও প্রয়োজন নেই"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"আপনার ফিঙ্গারপ্রিন্ট, ফেস মডেল বা \'স্ক্রিন লক\' ব্যবহার করে আপনি যে এনক্রিপটেড ডিজিটাল \'কী\' তৈরি করেন সেগুলিই হল \'পাসকী\'"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"আপনি যাতে অন্যান্য ডিভাইসে সাইন-ইন করতে পারেন তার জন্য Password Manager-এ এগুলি সেভ করা হয়"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> কোথায় সেভ করবেন তা বেছে নিন"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"আপনার পাসকী তৈরি করা"</string>
- <string name="save_your_password" msgid="6597736507991704307">"আপনার পাসওয়ার্ড সেভ করুন"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"আপনার সাইন-ইন করা সম্পর্কিত তথ্য সেভ করুন"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"আপনার তথ্য সেভ করতে একটি Password Manager বেছে নিন এবং পরের বার আরও ঝটপট সাইন-ইন করুন।"</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"আপনার <xliff:g id="CREATETYPES">%1$s</xliff:g> কোথায় সেভ করবেন তা বেছে নিন"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"আপনার তথ্য সেভ করতে একটি Password Manager বেছে নিন এবং পরের বার আরও দ্রুত সাইন-ইন করুন"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>-এর জন্য \'পাসকী\' তৈরি করবেন?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g>-এর জন্য পাসওয়ার্ড সেভ করবেন?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g>-এর জন্য সাইন-ইন সংক্রান্ত তথ্য সেভ করবেন?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"যেকোনও ডিভাইসে নিজের <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ব্যবহার করতে পারবেন। এটি <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>-এর জন্য <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>-এ সেভ করা হয়েছে।"</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="6372952459932674632">"অন্য একটি ডিভাইসে পাসকী তৈরি করবেন?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"অন্য ডিভাইসে পাসকী তৈরি করবেন?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"আপনার সব সাইন-ইনের জন্য <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ব্যবহার করবেন?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"এই Password Manager আপনার পাসওয়ার্ড ও পাসকী সেভ করবে, যাতে সহজেই সাইন-ইন করতে পারেন।"</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"এই Password Manager আপনার পাসওয়ার্ড ও পাসকী সেভ করবে যাতে সহজেই সাইন-ইন করতে পারেন"</string>
<string name="set_as_default" msgid="4415328591568654603">"ডিফল্ট হিসেবে সেট করুন"</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>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index 3d5db85..6b776f5 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Otkaži"</string>
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
<string name="string_more_options" msgid="7990658711962795124">"Više opcija"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Kreirajte na drugom mjestu"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Sačuvajte na drugom mjestu"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Koristite drugi uređaj"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Sačuvajte na drugom uređaju"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji ste uz pristupne ključeve"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne morate kreirati ili pamtiti složene lozinke"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi su šifrirani digitalni ključevi koje kreirate pomoću otiska prsta, lica ili zaključavanja ekrana"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Pristupni ključevi se pohranjuju u upravitelju lozinki da se možete prijaviti na drugim uređajima"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Odaberite gdje <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"kreiranje pristupnih ključeva"</string>
- <string name="save_your_password" msgid="6597736507991704307">"sačuvajte lozinku"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"sačuvajte informacije za prijavu"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Odaberite upravitelja lozinki da sačuvate svoje informacije i brže se prijavite sljedeći put."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite gdje sačuvati stavku <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Odaberite upravitelja lozinki da sačuvate svoje informacije i brže se prijavite sljedeći put"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Kreirati pristupni ključ za aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Sačuvati lozinku za aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Sačuvati informacije o prijavi za aplikaciju <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Možete koristiti vrstu akreditiva <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> na bilo kojem uređaju. Sačuvana je na usluzi <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> za račun <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"pristupni ključ"</string>
<string name="password" msgid="6738570945182936667">"lozinka"</string>
+ <string name="passkeys" msgid="5733880786866559847">"pristupni ključevi"</string>
+ <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čuvajte vrstu akreditiva \"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>\" na"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Kreirati pristupni ključ na drugom uređaju?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Kreirati pristupni ključ na drugom uređaju?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Koristiti uslugu <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> za sve vaše prijave?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ovaj upravitelj lozinki će pohraniti vaše lozinke i pristupne ključeve da vam olakša prijavu."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Ovaj upravitelj lozinki će pohraniti vaše lozinke i pristupne ključeve da vam olakša prijavu"</string>
<string name="set_as_default" msgid="4415328591568654603">"Postavi kao zadano"</string>
<string name="use_once" msgid="9027366575315399714">"Koristi jednom"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Broj lozinki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Broj pristupnih ključeva: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 350357a..8943f46 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel·la"</string>
<string name="string_continue" msgid="1346732695941131882">"Continua"</string>
<string name="string_more_options" msgid="7990658711962795124">"Més opcions"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Crea en un altre lloc"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Desa en un altre lloc"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Utilitza un altre dispositiu"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Desa en un altre dispositiu"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Més seguretat amb les claus d\'accés"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Amb les claus d\'accés, no cal que creïs ni recordis contrasenyes difícils"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les claus d\'accés són claus digitals encriptades que pots crear amb la teva cara, l\'empremta digital o el bloqueig de pantalla"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Es desen a un gestor de contrasenyes perquè puguis iniciar la sessió en altres dispositius"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Tria on vols <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crea les teves claus d\'accés"</string>
- <string name="save_your_password" msgid="6597736507991704307">"desar la contrasenya"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"desar la teva informació d\'inici de sessió"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecciona un gestor de contrasenyes per desar la teva informació i iniciar la sessió més ràpidament la pròxima vegada."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vols crear la clau d\'accés per a <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vols desar la contrasenya per a <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vols desar la informació d\'inici de sessió per a <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Pots utilitzar <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> en qualsevol dispositiu. Està desat a <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> per a <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"clau d\'accés"</string>
<string name="password" msgid="6738570945182936667">"contrasenya"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"inicis de sessió"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informació d\'inici de sessió"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Desa <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> a"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vols crear una clau d\'accés en un altre dispositiu?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vols utilitzar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> per a tots els teus inicis de sessió?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Aquest gestor de contrasenyes emmagatzemarà les teves contrasenyes i claus d\'accés per ajudar-te a iniciar la sessió fàcilment."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Estableix com a predeterminada"</string>
<string name="use_once" msgid="9027366575315399714">"Utilitza un cop"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contrasenyes • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> claus d\'accés"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index 199bce3..06f94d2 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Zrušit"</string>
<string name="string_continue" msgid="1346732695941131882">"Pokračovat"</string>
<string name="string_more_options" msgid="7990658711962795124">"Další možnosti"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Vytvořit na jiném místě"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Uložit na jiné místo"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Použít jiné zařízení"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Uložit do jiného zařízení"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Přístupové klíče zvyšují bezpečnost"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"S přístupovými klíči si nemusíte vytvářet ani pamatovat složitá hesla"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Přístupové klíče jsou šifrované digitální klíče, které vytvoříte pomocí otisku prstu, obličeje nebo zámku obrazovky"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Přístupové klíče se ukládají do správce hesel, takže se můžete přihlásit na jiných zařízeních"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Zvolte, kde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"vytvářet přístupové klíče"</string>
- <string name="save_your_password" msgid="6597736507991704307">"uložte si heslo"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"uložte své přihlašovací údaje"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Vyberte správce hesel k uložení svých údajů, abyste se příště mohli přihlásit rychleji."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vytvořit přístupový klíč pro aplikaci <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Uložit heslo pro aplikaci <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Uložit přihlašovací údaje pro aplikaci <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Své identifikační údaje typu <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> pro aplikaci <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> můžete používat na libovolném zařízení. Ukládá se do <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> pro uživatele <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"přístupový klíč"</string>
<string name="password" msgid="6738570945182936667">"heslo"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"přihlášení"</string>
<string name="sign_in_info" msgid="2627704710674232328">"přihlašovací údaje"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Uložit <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> do"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vytvořit přístupový klíč v jiném zařízení?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Používat <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pro všechna přihlášení?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Tento správce hesel bude ukládat vaše hesla a přístupové klíče, abyste se mohli snadno přihlásit."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Nastavit jako výchozí"</string>
<string name="use_once" msgid="9027366575315399714">"Použít jednou"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Hesla: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Přístupové klíče: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index e8ff4d4..4c68886 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Annuller"</string>
<string name="string_continue" msgid="1346732695941131882">"Fortsæt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Flere valgmuligheder"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Opret et andet sted"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Gem et andet sted"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Brug en anden enhed"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Gem på en anden enhed"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Øget beskyttelse med adgangsnøgler"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Når du bruger adgangsnøgler, behøver du ikke at oprette eller huske avancerede adgangskoder"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Adgangsnøgler er krypterede digitale nøgler, som du opretter ved hjælp af fingeraftryk, ansigtsgenkendelse eller skærmlås"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Disse gemmes i en adgangskodeadministrator, så du kan logge ind på andre enheder"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Vælg, hvor du vil <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"oprette dine adgangsnøgler"</string>
- <string name="save_your_password" msgid="6597736507991704307">"gem din adgangskode"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"gem dine loginoplysninger"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Vælg en adgangskodeadministrator for at gemme dine oplysninger, så du kan logge ind hurtigere næste gang."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vil du oprette en adgangsnøgle til <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vil du gemme adgangskoden til <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vil du gemme loginoplysningerne til <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Du kan bruge din <xliff:g id="APPDOMAINNAME">%1$s</xliff:g>-<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> på enhver enhed. Den gemmes i <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"adgangsnøgle"</string>
<string name="password" msgid="6738570945182936667">"adgangskode"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"loginmetoder"</string>
<string name="sign_in_info" msgid="2627704710674232328">"loginoplysninger"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Gem <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> her:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vil du oprette en adgangsnøgle i en anden enhed?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vil du bruge <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> til alle dine loginmetoder?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Denne adgangskodeadministrator gemmer dine adgangskoder og adgangsnøgler for at hjælpe dig med nemt at logge ind."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Angiv som standard"</string>
<string name="use_once" msgid="9027366575315399714">"Brug én gang"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> adgangskoder • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> adgangsnøgler"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index 0d569e4..d26f430 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Abbrechen"</string>
<string name="string_continue" msgid="1346732695941131882">"Weiter"</string>
<string name="string_more_options" msgid="7990658711962795124">"Weitere Optionen"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"An anderem Speicherort erstellen"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"An anderem Ort speichern"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Anderes Gerät verwenden"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Auf einem anderen Gerät speichern"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mehr Sicherheit mit Passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mit Passkeys musst du keine komplizierten Passwörter erstellen oder dir merken"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys sind verschlüsselte digitale Schlüssel, die du mithilfe deines Fingerabdrucks, Gesichts oder deiner Displaysperre erstellst"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Sie werden in einem Passwortmanager gespeichert, damit du dich auf anderen Geräten anmelden kannst"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Ort auswählen für: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"Passkeys erstellen"</string>
- <string name="save_your_password" msgid="6597736507991704307">"Passwort speichern"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"Anmeldedaten speichern"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Du kannst einen Passwortmanager auswählen, um deine Anmeldedaten zu speichern, damit du dich nächstes Mal schneller anmelden kannst."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Passkey für <xliff:g id="APPNAME">%1$s</xliff:g> erstellen?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Passwort für <xliff:g id="APPNAME">%1$s</xliff:g> speichern?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Anmeldedaten für <xliff:g id="APPNAME">%1$s</xliff:g> speichern?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Du kannst Folgendes von <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> auf jedem beliebigen Gerät verwenden: <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>. Diese Anmeldeoption wird für <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> in <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> gespeichert."</string>
<string name="passkey" msgid="632353688396759522">"Passkey"</string>
<string name="password" msgid="6738570945182936667">"Passwort"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="create_passkey_in_other_device_title" msgid="6372952459932674632">"Passkey auf anderem Gerät erstellen?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> für alle Anmeldungen verwenden?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Mit diesem Passwortmanager werden deine Passwörter und Passkeys gespeichert, damit du dich problemlos anmelden kannst."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Als Standard festlegen"</string>
<string name="use_once" msgid="9027366575315399714">"Einmal verwenden"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> Passwörter • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> Passkeys"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index d76e1a0..3fb6506 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Ακύρωση"</string>
<string name="string_continue" msgid="1346732695941131882">"Συνέχεια"</string>
<string name="string_more_options" msgid="7990658711962795124">"Περισσότερες επιλογές"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Δημιουργία σε άλλη θέση"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Αποθήκευση σε άλλη θέση"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Χρήση άλλης συσκευής"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Αποθήκευση σε άλλη συσκευή"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Μεγαλύτερη ασφάλεια με κλειδιά πρόσβασης"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Με τα κλειδιά πρόσβασης, δεν χρειάζεται να δημιουργείτε ή να θυμάστε σύνθετους κωδικούς πρόσβασης."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Τα κλειδιά πρόσβασης είναι κρυπτογραφημένα ψηφιακά κλειδιά που δημιουργείτε χρησιμοποιώντας το δακτυλικό σας αποτύπωμα, το πρόσωπο ή το κλείδωμα οθόνης."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Αποθηκεύονται σε ένα πρόγραμμα διαχείρισης κωδικών πρόσβασης, για να μπορείτε να συνδέεστε από άλλες συσκευές."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Επιλέξτε θέση για <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"δημιουργήστε τα κλειδιά πρόσβασής σας"</string>
- <string name="save_your_password" msgid="6597736507991704307">"αποθήκευση του κωδικού πρόσβασής σας"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"αποθήκευση των στοιχείων σύνδεσής σας"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Επιλέξτε ένα πρόγραμμα διαχείρισης κωδικών πρόσβασης για να αποθηκεύσετε τα στοιχεία σας και να συνδεθείτε πιο γρήγορα την επόμενη φορά."</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="5220979185879006862">"Δημιουργία κλειδιού πρόσβασης για <xliff:g id="APPNAME">%1$s</xliff:g>;"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Αποθήκευση κωδικού πρόσβασης για <xliff:g id="APPNAME">%1$s</xliff:g>;"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Αποθήκευση στοιχείων σύνδεσης για <xliff:g id="APPNAME">%1$s</xliff:g>;"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Μπορείτε να χρησιμοποιήσετε το στοιχείο τύπου <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> του τομέα <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> σε οποιαδήποτε συσκευή. Αποθηκεύτηκε στο <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> για τον χρήστη <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</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="6372952459932674632">"Δημιουργία κλειδιού πρόσβασης σε άλλη συσκευή;"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Δημιουργία κλειδιού πρόσβασης σε άλλη συσκευή;"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Να χρησιμοποιηθεί το <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> για όλες τις συνδέσεις σας;"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Αυτός ο διαχειριστής κωδικών πρόσβασης θα αποθηκεύει τους κωδικούς πρόσβασης και τα κλειδιά πρόσβασης, για να συνδέεστε εύκολα."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Αυτός ο διαχειριστής κωδικών πρόσβασης θα αποθηκεύει τους κωδικούς πρόσβασης και τα κλειδιά πρόσβασης, για να συνδέεστε εύκολα."</string>
<string name="set_as_default" msgid="4415328591568654603">"Ορισμός ως προεπιλογής"</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>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index 5315d32..0bccea1 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel"</string>
<string name="string_continue" msgid="1346732695941131882">"Continue"</string>
<string name="string_more_options" msgid="7990658711962795124">"More options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Create in another place"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Save to another place"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Use another device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Save to another device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"They are saved to a password manager, so that you can sign in on other devices"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choose where to <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"create your passkeys"</string>
- <string name="save_your_password" msgid="6597736507991704307">"save your password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"save your sign-in info"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Select a password manager to save your info and sign in faster next time."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Save password for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"You can use your <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> on any device. It is saved to <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+ <string name="passwords" msgid="5419394230391253816">"passwords"</string>
<string name="sign_ins" msgid="4710739369149469208">"sign-ins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sign-in info"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Create a passkey in another device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"This password manager will store your passwords and passkeys to help you easily sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
<string name="use_once" msgid="9027366575315399714">"Use once"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index 7917d0a..38637df 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel"</string>
<string name="string_continue" msgid="1346732695941131882">"Continue"</string>
<string name="string_more_options" msgid="7990658711962795124">"More options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Create in another place"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Save to another place"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Use another device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Save to another device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"They are saved to a password manager, so you can sign in on other devices"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choose where to <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"create your passkeys"</string>
- <string name="save_your_password" msgid="6597736507991704307">"save your password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"save your sign-in info"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Select a password manager to save your info and sign in faster next time."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Save password for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"You can use your <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> on any device. It is saved to <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+ <string name="passwords" msgid="5419394230391253816">"passwords"</string>
<string name="sign_ins" msgid="4710739369149469208">"sign-ins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sign-in info"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Create a passkey in another device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey in another device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"This password manager will store your passwords and passkeys to help you easily sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
<string name="use_once" msgid="9027366575315399714">"Use once"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index 5315d32..0bccea1 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel"</string>
<string name="string_continue" msgid="1346732695941131882">"Continue"</string>
<string name="string_more_options" msgid="7990658711962795124">"More options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Create in another place"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Save to another place"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Use another device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Save to another device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"They are saved to a password manager, so that you can sign in on other devices"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choose where to <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"create your passkeys"</string>
- <string name="save_your_password" msgid="6597736507991704307">"save your password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"save your sign-in info"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Select a password manager to save your info and sign in faster next time."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Save password for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"You can use your <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> on any device. It is saved to <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+ <string name="passwords" msgid="5419394230391253816">"passwords"</string>
<string name="sign_ins" msgid="4710739369149469208">"sign-ins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sign-in info"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Create a passkey in another device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"This password manager will store your passwords and passkeys to help you easily sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
<string name="use_once" msgid="9027366575315399714">"Use once"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index 5315d32..0bccea1 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel"</string>
<string name="string_continue" msgid="1346732695941131882">"Continue"</string>
<string name="string_more_options" msgid="7990658711962795124">"More options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Create in another place"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Save to another place"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Use another device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Save to another device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys that you create using your fingerprint, face or screen lock"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"They are saved to a password manager, so that you can sign in on other devices"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choose where to <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"create your passkeys"</string>
- <string name="save_your_password" msgid="6597736507991704307">"save your password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"save your sign-in info"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Select a password manager to save your info and sign in faster next time."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Save password for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"You can use your <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> on any device. It is saved to <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+ <string name="passwords" msgid="5419394230391253816">"passwords"</string>
<string name="sign_ins" msgid="4710739369149469208">"sign-ins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sign-in info"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Create a passkey in another device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey on another device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"This password manager will store your passwords and passkeys to help you easily sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
<string name="use_once" msgid="9027366575315399714">"Use once"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 357efc1..081cfe8 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancel"</string>
<string name="string_continue" msgid="1346732695941131882">"Continue"</string>
<string name="string_more_options" msgid="7990658711962795124">"More options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Create in another place"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Save to another place"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Use another device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Save to another device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Safer with passkeys"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"With passkeys, you don’t need to create or remember complex passwords"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"They are saved to a password manager, so you can sign in on other devices"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choose where to <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"create your passkeys"</string>
- <string name="save_your_password" msgid="6597736507991704307">"save your password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"save your sign-in info"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Select a password manager to save your info and sign in faster next time."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Choose where to save your <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Select a password manager to save your info and sign in faster next time"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Create passkey for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Save password for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Save sign-in info for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"You can use your <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> on any device. It is saved to <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"passkeys"</string>
+ <string name="passwords" msgid="5419394230391253816">"passwords"</string>
<string name="sign_ins" msgid="4710739369149469208">"sign-ins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sign-in info"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Save <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> to"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Create a passkey in another device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Create passkey in another device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Use <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for all your sign-ins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"This password manager will store your passwords and passkeys to help you easily sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"This password manager will store your passwords and passkeys to help you easily sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Set as default"</string>
<string name="use_once" msgid="9027366575315399714">"Use once"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passwords • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkeys"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index acc9240a..9a6c3f3 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Crear en otra ubicación"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Guardar en otra ubicación"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar otro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Guardar en otro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con llaves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no es necesario crear ni recordar contraseñas complejas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales encriptadas que puedes crear usando tu huella dactilar, rostro o bloqueo de pantalla"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Se guardan en un administrador de contraseñas para que puedas acceder en otros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Elige dónde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crea tus llaves de acceso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"guardar tu contraseña"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"guardar tu información de acceso"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecciona un administrador de contraseñas para guardar la información y acceder más rápido la próxima vez."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"¿Quieres crear una llave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"¿Quieres guardar la contraseña para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"¿Quieres guardar la información de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Puedes usar tu <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> en cualquier dispositivo. Se guardó en <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> para <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"llave de acceso"</string>
<string name="password" msgid="6738570945182936667">"contraseña"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"accesos"</string>
<string name="sign_in_info" msgid="2627704710674232328">"información de acceso"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Guardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"¿Quieres crear una llave de acceso en otro dispositivo?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"¿Quieres usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos tus accesos?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este administrador de contraseñas almacenará tus contraseñas y llaves de acceso para ayudarte a acceder fácilmente."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Establecer como predeterminado"</string>
<string name="use_once" msgid="9027366575315399714">"Usar una vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> llaves de acceso"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index 034a9ca..73f6e2f 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Más opciones"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Crear en otro lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Guardar en otro lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar otro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Guardar en otro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Más seguridad con las llaves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con las llaves de acceso, no tienes que crear ni recordar contraseñas complicadas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Las llaves de acceso son claves digitales cifradas que puedes crear con tu huella digital, cara o bloqueo de pantalla"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Se guardan en un gestor de contraseñas para que puedas iniciar sesión en otros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Elige dónde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crea tus llaves de acceso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"guardar tu contraseña"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"guardar tu información de inicio de sesión"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecciona un gestor de contraseñas para guardar tu información e iniciar sesión más rápido la próxima vez."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"¿Crear llave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"¿Guardar la contraseña de <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"¿Guardar la información de inicio de sesión de <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Puedes usar tu <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> de <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> en cualquier dispositivo. Se guarda en <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> para <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"llave de acceso"</string>
<string name="password" msgid="6738570945182936667">"contraseña"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"inicios de sesión"</string>
<string name="sign_in_info" msgid="2627704710674232328">"información de inicio de sesión"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Guardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"¿Crear una llave de acceso en otro dispositivo?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"¿Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos tus inicios de sesión?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este gestor de contraseñas almacenará tus contraseñas y llaves de acceso para que puedas iniciar sesión fácilmente."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Fijar como predeterminado"</string>
<string name="use_once" msgid="9027366575315399714">"Usar una vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contraseñas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> llaves de acceso"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index 7277674..597ad7f 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Tühista"</string>
<string name="string_continue" msgid="1346732695941131882">"Jätka"</string>
<string name="string_more_options" msgid="7990658711962795124">"Rohkem valikuid"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Loo teises kohas"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Salvesta teise kohta"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Kasuta teist seadet"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Salvesta teise seadmesse"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Pääsuvõtmed suurendavad turvalisust"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Pääsuvõtmetega ei pea te looma ega meelde jätma keerukaid paroole"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pääsuvõtmed on digitaalsed krüpteeritud võtmed, mille loote sõrmejälje, näo või ekraanilukuga"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Need salvestatakse paroolihaldurisse, et saaksite teistes seadmetes sisse logida"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Valige, kus <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"looge oma pääsuvõtmed"</string>
- <string name="save_your_password" msgid="6597736507991704307">"parool salvestada"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"sisselogimisandmed salvestada"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Valige paroolihaldur, et salvestada oma teave ja järgmisel korral kiiremini sisse logida."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Kas luua rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks pääsuvõti?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Kas salvestada rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks parool?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Kas salvestada rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> jaoks sisselogimisandmed?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Saate üksust <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> kasutada mis tahes seadmes. See salvestatakse teenusesse <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> kasutaja <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> jaoks"</string>
<string name="passkey" msgid="632353688396759522">"pääsukood"</string>
<string name="password" msgid="6738570945182936667">"parool"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"sisselogimisandmed"</string>
<string name="sign_in_info" msgid="2627704710674232328">"sisselogimisteave"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Salvestage <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Kas luua pääsuvõti teises seadmes?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Kas kasutada teenust <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kõigi teie sisselogimisandmete puhul?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"See paroolihaldur salvestab teie paroolid ja pääsuvõtmed, et aidata teil hõlpsalt sisse logida."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Määra vaikeseadeks"</string>
<string name="use_once" msgid="9027366575315399714">"Kasuta ühe korra"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parooli • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> pääsuvõtit"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index a0e1f38..0178141 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Utzi"</string>
<string name="string_continue" msgid="1346732695941131882">"Egin aurrera"</string>
<string name="string_more_options" msgid="7990658711962795124">"Aukera gehiago"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Sortu beste toki batean"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Gorde beste toki batean"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Erabili beste gailu bat"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Gorde beste gailu batean"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sarbide-gako seguruagoak"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Sarbide-gakoei esker, ez duzu pasahitz konplexurik sortu edo gogoratu beharrik"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Hatz-marka, aurpegia edo pantailaren blokeoa erabilita sortzen dituzun giltza digital enkriptatuak dira sarbide-gakoak"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Pasahitz-kudeatzaile batean gordetzen dira, beste gailu batzuen bidez saioa hasi ahal izateko"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Aukeratu non <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"sortu sarbide-gakoak"</string>
- <string name="save_your_password" msgid="6597736507991704307">"gorde pasahitza"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"gorde kredentzialei buruzko informazioa"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Hautatu informazioa gordetzeko pasahitz-kudeatzaile bat eta hasi saioa bizkorrago hurrengoan."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> atzitzeko sarbide-gako bat sortu nahi duzu?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioko pasahitza gorde nahi duzu?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioko saioa hasteko informazioa gorde nahi duzu?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> aplikazioko <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> gailu guztietan erabil dezakezu. <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> aplikazioan dago gordeta (<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>)."</string>
<string name="passkey" msgid="632353688396759522">"sarbide-gakoa"</string>
<string name="password" msgid="6738570945182936667">"pasahitza"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"kredentzialak"</string>
<string name="sign_in_info" msgid="2627704710674232328">"saioa hasteko informazioa"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Gorde <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> hemen:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Sarbide-gako bat sortu nahi duzu beste gailu batean?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> erabili nahi duzu kredentzial guztietarako?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Pasahitz-kudeatzaile honek pasahitzak eta sarbide-gakoak gordeko ditu saioa erraz has dezazun."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Ezarri lehenetsi gisa"</string>
<string name="use_once" msgid="9027366575315399714">"Erabili behin"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> pasahitz • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> sarbide-gako"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 18099c9..1b11819 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"لغو"</string>
<string name="string_continue" msgid="1346732695941131882">"ادامه"</string>
<string name="string_more_options" msgid="7990658711962795124">"گزینههای بیشتر"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"ایجاد در مکانی دیگر"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ذخیره در مکانی دیگر"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"استفاده از دستگاهی دیگر"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ذخیره در دستگاهی دیگر"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"فضایی ایمنتر با گذرکلید"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"با گذرکلیدها، لازم نیست گذرواژه پیچیدهای بسازید یا آن را بهخاطر بسپارید"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"گذرکلیدها کلیدهای دیجیتالی رمزگذاریشدهای هستند که بااستفاده از اثر انگشت، چهره، یا قفل صفحه ایجاد میکنید"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"گذرکلیدها در «مدیر گذرواژه» ذخیره میشود تا بتوانید در دستگاههای دیگر به سیستم وارد شوید"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"انتخاب محل <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ایجاد گذرکلید"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ذخیره گذرواژه"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ذخیره اطلاعات ورود به سیستم"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"مدیر گذرواژهای انتخاب کنید تا اطلاعاتتان ذخیره شود و دفعه بعدی سریعتر به سیستم وارد شوید."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"برای <xliff:g id="APPNAME">%1$s</xliff:g> گذرکلید ایجاد شود؟"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"گذرواژه <xliff:g id="APPNAME">%1$s</xliff:g> ذخیره شود؟"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"اطلاعات ورود به سیستم <xliff:g id="APPNAME">%1$s</xliff:g> ذخیره شود؟"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"میتوانید از <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> در هر دستگاهی استفاده کنید. این مورد در <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> برای <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> ذخیره میشود."</string>
<string name="passkey" msgid="632353688396759522">"گذرکلید"</string>
<string name="password" msgid="6738570945182936667">"گذرواژه"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"گذرکلید در دستگاهی دیگر ایجاد شود؟"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"از <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> برای همه ورود به سیستمها استفاده شود؟"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"این مدیر گذرواژه گذرکلیدها و گذرواژههای شما را ذخیره خواهد کرد تا بهراحتی بتوانید به سیستم وارد شوید."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"تنظیم بهعنوان پیشفرض"</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>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index ef7adc0..bdb55fb 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Peru"</string>
<string name="string_continue" msgid="1346732695941131882">"Jatka"</string>
<string name="string_more_options" msgid="7990658711962795124">"Lisäasetukset"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Luo muualla"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Tallenna muualle"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Käytä toista laitetta"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Tallenna toiselle laitteelle"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Turvallisuutta avainkoodeilla"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kun käytät avainkoodeja, sinun ei tarvitse luoda tai muistaa monimutkaisia salasanoja"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Avainkoodit ovat salattuja digitaalisia avaimia, joita voit luoda sormenjäljen, kasvojen tai näytön lukituksen avulla"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ne tallennetaan salasanojen ylläpito-ohjelmaan, jotta voit kirjautua sisään muilla laitteilla"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Valitse paikka: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"luo avainkoodeja"</string>
- <string name="save_your_password" msgid="6597736507991704307">"tallenna salasanasi"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"tallenna kirjautumistiedot"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Valitse salasanojen ylläpito-ohjelma, niin voit tallentaa tietosi ja kirjautua ensi kerralla nopeammin sisään."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Luodaanko avainkoodi (<xliff:g id="APPNAME">%1$s</xliff:g>)?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Tallennetaanko salasana (<xliff:g id="APPNAME">%1$s</xliff:g>)?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Tallennetaanko kirjautumistiedot (<xliff:g id="APPNAME">%1$s</xliff:g>)?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> (<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>) on käytettävissä millä tahansa laitteella. Se tallennetaan tänne: <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> (<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>)."</string>
<string name="passkey" msgid="632353688396759522">"avainkoodi"</string>
<string name="password" msgid="6738570945182936667">"salasana"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"sisäänkirjautumiset"</string>
<string name="sign_in_info" msgid="2627704710674232328">"kirjautumistiedot"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Tallenna <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> tänne:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Luodaanko avainkoodi toisella laitteella?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Otetaanko <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> käyttöön kaikissa sisäänkirjautumisissa?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Tämä salasanojen ylläpitotyökalu tallentaa salasanat ja avainkoodit, jotta voit kirjautua helposti sisään."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Aseta oletukseksi"</string>
<string name="use_once" msgid="9027366575315399714">"Käytä kerran"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> salasanaa • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> avainkoodia"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 25b907d..1e4b009 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Annuler"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
<string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Créer à un autre emplacement"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Enregistrer à un autre emplacement"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Utiliser un autre appareil"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Enregistrer sur un autre appareil"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Une sécurité accrue grâce aux clés d\'accès"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, nul besoin de créer ou de mémoriser des mots de passe complexes"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez en utilisant votre empreinte digitale, votre visage ou le verrouillage de votre écran"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ils sont enregistrés dans un gestionnaire de mots de passe pour vous permettre de vous connecter sur d\'autres appareils"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choisir où <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"créer vos clés d\'accès"</string>
- <string name="save_your_password" msgid="6597736507991704307">"enregistrer votre mot de passe"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"enregistrer vos données de connexion"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos renseignements et vous connecter plus rapidement la prochaine fois."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Créer une clé d\'accès pour <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Enregistrer le mot de passe pour <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Enregistrer les renseignements de connexion pour <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Vous pouvez utiliser votre <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> sur n\'importe quel appareil. Il est enregistré sur <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> pour <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"clé d\'accès"</string>
<string name="password" msgid="6738570945182936667">"mot de passe"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"connexions"</string>
<string name="sign_in_info" msgid="2627704710674232328">"renseignements de connexion"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Enregistrer <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> dans"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Créer une clé d\'accès dans un autre appareil?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Utiliser <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pour toutes vos connexions?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ce gestionnaire de mots de passe va enregistrer vos mots de passe et vos clés d\'accès pour vous aider à vous connecter facilement."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Définir par défaut"</string>
<string name="use_once" msgid="9027366575315399714">"Utiliser une fois"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mots de passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> clés d\'accès"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index fe5d894..7073ca6 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Annuler"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
<string name="string_more_options" msgid="7990658711962795124">"Autres options"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Créer ailleurs"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Enregistrer ailleurs"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Utiliser un autre appareil"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Enregistrer sur un autre appareil"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sécurité renforcée grâce aux clés d\'accès"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Avec les clés d\'accès, plus besoin de créer ni de mémoriser des mots de passe complexes"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Les clés d\'accès sont des clés numériques chiffrées que vous créez à l\'aide de votre empreinte digitale, de votre visage ou du verrouillage de l\'écran"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elles sont enregistrées dans un gestionnaire de mots de passe pour que vous puissiez vous connecter sur d\'autres appareils"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Choisir où <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"créer vos clés d\'accès"</string>
- <string name="save_your_password" msgid="6597736507991704307">"enregistrer votre mot de passe"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"enregistrer vos informations de connexion"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Sélectionnez un gestionnaire de mots de passe pour enregistrer vos informations et vous connecter plus rapidement la prochaine fois."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Créer une clé d\'accès pour <xliff:g id="APPNAME">%1$s</xliff:g> ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Enregistrer le mot de passe pour <xliff:g id="APPNAME">%1$s</xliff:g> ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Enregistrer les informations de connexion pour <xliff:g id="APPNAME">%1$s</xliff:g> ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Vous pouvez utiliser votre <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> sur n\'importe quel appareil. Elle est enregistrée dans le <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> de <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"clé d\'accès"</string>
<string name="password" msgid="6738570945182936667">"mot de passe"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"connexions"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informations de connexion"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Enregistrer la <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> dans"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Créer une clé d\'accès dans un autre appareil ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Utiliser <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pour toutes vos connexions ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ce gestionnaire de mots de passe stockera vos mots de passe et clés d\'accès pour vous permettre de vous connecter facilement."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Définir par défaut"</string>
<string name="use_once" msgid="9027366575315399714">"Utiliser une fois"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mot(s) de passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> clé(s) d\'accès"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index d6b56f7..5b6e719 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Máis opcións"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Crear noutro lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Gardar noutro lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar outro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Gardar noutro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Máis protección coas claves de acceso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Cunha clave de acceso, non é necesario que crees ou lembres contrasinais complexos"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As claves de acceso son claves dixitais encriptadas que creas usando a túa impresión dixital, a túa cara ou o teu bloqueo de pantalla"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"As claves de acceso gárdanse nun xestor de contrasinais para que poidas iniciar sesión noutros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Escolle onde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crear as túas claves de acceso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"gardar o contrasinal"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"gardar a información de inicio de sesión"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecciona un xestor de contrasinais para gardar a túa información e iniciar sesión máis rápido a próxima vez."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Queres crear unha clave de acceso para <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Queres gardar o contrasinal de <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Queres gardar a información de inicio de sesión de <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Podes usar a túa <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> de <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> en calquera dispositivo. Gárdase en <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> para <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"clave de acceso"</string>
<string name="password" msgid="6738570945182936667">"contrasinal"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"métodos de inicio de sesión"</string>
<string name="sign_in_info" msgid="2627704710674232328">"información de inicio de sesión"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Gardar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> en"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Queres crear unha clave de acceso noutro dispositivo?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Queres usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> cada vez que inicies sesión?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este xestor de contrasinais almacenará os contrasinais e as claves de acceso para axudarche a iniciar sesión facilmente."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Establecer como predeterminado"</string>
<string name="use_once" msgid="9027366575315399714">"Usar unha vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> contrasinais • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> claves de acceso"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index e497663..fdaf586 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"રદ કરો"</string>
<string name="string_continue" msgid="1346732695941131882">"ચાલુ રાખો"</string>
<string name="string_more_options" msgid="7990658711962795124">"વધુ વિકલ્પો"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"કોઈ અન્ય સ્થાન પર બનાવો"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"કોઈ અન્ય સ્થાન પર સાચવો"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"કોઈ અન્ય ડિવાઇસનો ઉપયોગ કરો"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"અન્ય ડિવાઇસ પર સાચવો"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"પાસકી સાથે વધુ સલામત"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"પાસકી હોવાથી, તમારે જટિલ પાસવર્ડ બનાવવાની કે યાદ રાખવાની જરૂર રહેતી નથી"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"પાસકી એ એન્ક્રિપ્ટેડ ડિજિટલ કી છે, જેને તમે તમારી ફિંગરપ્રિન્ટ, ચહેરા અથવા સ્ક્રીન લૉકનો ઉપયોગ કરીને બનાવો છો"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"તેને પાસવર્ડ મેનેજરમાં સાચવવામાં આવે છે, જેથી તમે અન્ય ડિવાઇસમાં સાઇન ઇન ન કરી શકો"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> ક્યાં સાચવવી છે, તે પસંદ કરો"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"તમારી પાસકી બનાવો"</string>
- <string name="save_your_password" msgid="6597736507991704307">"તમારો પાસવર્ડ સાચવો"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"તમારી સાઇન-ઇનની માહિતી સાચવો"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"તમારી માહિતી સાચવવા માટે પાસવર્ડ મેનેજર પસંદ કરો અને આગલી વખતે વધુ ઝડપથી સાઇન ઇન કરો."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> માટે પાસકી બનાવીએ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> માટે પાસવર્ડ સાચવીએ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> માટે સાઇન-ઇન કરવાની માહિતી સાચવીએ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"તમે કોઈપણ ડિવાઇસ પર તમારા <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>નો ઉપયોગ કરી શકો છો. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> માટે <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>માં તેને સાચવવામાં આવે છે."</string>
<string name="passkey" msgid="632353688396759522">"પાસકી"</string>
<string name="password" msgid="6738570945182936667">"પાસવર્ડ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"શું અન્ય ડિવાઇસમાં પાસકી બનાવવા માગો છો?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"શું તમારા બધા સાઇન-ઇન માટે <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>નો ઉપયોગ કરીએ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"આ પાસવર્ડ મેનેજર તમને સરળતાથી સાઇન ઇન કરવામાં સહાય કરવા માટે, તમારા પાસવર્ડ અને પાસકીને સ્ટોર કરશે."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ડિફૉલ્ટ તરીકે સેટ કરો"</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>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index c0d53a0..f75a989 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"रद्द करें"</string>
<string name="string_continue" msgid="1346732695941131882">"जारी रखें"</string>
<string name="string_more_options" msgid="7990658711962795124">"ज़्यादा विकल्प"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"दूसरी जगह पर बनाएं"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"दूसरी जगह पर सेव करें"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"दूसरे डिवाइस का इस्तेमाल करें"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"दूसरे डिवाइस पर सेव करें"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकी के साथ सुरक्षित रहें"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकी होने पर, आपको जटिल पासवर्ड बनाने या याद रखने की ज़रूरत नहीं पड़ती"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी, एन्क्रिप्ट (सुरक्षित) की गई डिजिटल की होती हैं. इन्हें फ़िंगरप्रिंट, चेहरे या स्क्रीन लॉक का इस्तेमाल करके बनाया जाता है"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"पासकी को पासवर्ड मैनेजर में सेव किया जाता है, ताकि इनका इस्तेमाल करके आप अन्य डिवाइसों में साइन इन कर सकें"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"चुनें कि <xliff:g id="CREATETYPES">%1$s</xliff:g> कहां पर सेव करना है"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"अपनी पासकी बनाएं"</string>
- <string name="save_your_password" msgid="6597736507991704307">"अपना पासवर्ड सेव करें"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"साइन इन से जुड़ी अपनी जानकारी सेव करें"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"अपनी जानकारी सेव करने के लिए, कोई पासवर्ड मैनेजर चुनें और अगली बार तेज़ी से साइन इन करें."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए पासकी बनानी है?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए पासवर्ड सेव करना है?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"क्या आपको <xliff:g id="APPNAME">%1$s</xliff:g> के लिए साइन-इन की जानकारी सेव करनी है?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"अपने <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> को किसी भी डिवाइस पर इस्तेमाल किया जा सकता है. इसे <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> के लिए, <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> में सेव किया जाता है."</string>
<string name="passkey" msgid="632353688396759522">"पासकी"</string>
<string name="password" msgid="6738570945182936667">"पासवर्ड"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"क्या आपको किसी दूसरे डिवाइस में पासकी बनानी है?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"क्या आपको साइन इन से जुड़ी सारी जानकारी सेव करने के लिए, <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> का इस्तेमाल करना है?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"पासवर्ड और पासकी को इस पासवर्ड मैनेजर में सेव करके, आसानी से साइन इन किया जा सकता है."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"डिफ़ॉल्ट के तौर पर सेट करें"</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>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 0a171cc..2f9e46b 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Odustani"</string>
<string name="string_continue" msgid="1346732695941131882">"Nastavi"</string>
<string name="string_more_options" msgid="7990658711962795124">"Više opcija"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Izradi na drugom mjestu"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Spremi na drugom mjestu"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Upotrijebite neki drugi uređaj"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Spremi na drugi uređaj"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Sigurniji s pristupnim ključevima"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Uz pristupne ključeve ne trebate izrađivati ili pamtiti složene zaporke"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Pristupni ključevi šifrirani su digitalni ključevi koje izrađujete pomoću svojeg otiska prsta, lica ili zaključavanja zaslona"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Spremaju se u upravitelju zaporki kako biste se mogli prijaviti na drugim uređajima"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Odaberite mjesto za sljedeće: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"izradite pristupne ključeve"</string>
- <string name="save_your_password" msgid="6597736507991704307">"spremi zaporku"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"spremi podatke za prijavu"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Odaberite upravitelja zaporki kako biste spremili svoje informacije i drugi se put brže prijavili."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Odaberite mjesto za spremanje: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Odaberite upravitelja zaporki kako biste spremili svoje informacije i drugi se put brže prijavili"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Izraditi pristupni ključ za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Spremiti zaporku za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Spremiti informacije o prijavi za <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Aplikaciju <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> možete upotrijebiti na bilo kojem uređaju. Sprema se na uslugu <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> za: <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"pristupni ključ"</string>
<string name="password" msgid="6738570945182936667">"zaporka"</string>
+ <string name="passkeys" msgid="5733880786866559847">"pristupni ključevi"</string>
+ <string name="passwords" msgid="5419394230391253816">"zaporke"</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">"Spremi <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> u"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Želite li izraditi pristupni ključ na nekom drugom uređaju?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Želite li izraditi pristupni ključ na drugom uređaju?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite li upotrebljavati uslugu <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> za sve prijave?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Upravitelj zaporki pohranit će vaše zaporke i pristupne ključeve radi jednostavnije prijave."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Upravitelj zaporki pohranit će vaše zaporke i pristupne ključeve radi jednostavnije prijave"</string>
<string name="set_as_default" msgid="4415328591568654603">"Postavi kao zadano"</string>
<string name="use_once" msgid="9027366575315399714">"Upotrijebi jednom"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Broj zaporki: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • broj pristupnih ključeva: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index 6a7531a..81616df 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Mégse"</string>
<string name="string_continue" msgid="1346732695941131882">"Folytatás"</string>
<string name="string_more_options" msgid="7990658711962795124">"További lehetőségek"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Létrehozás másik helyen"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Mentés másik helyre"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Másik eszköz használata"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Mentés másik eszközre"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Fokozott biztonság – azonosítókulccsal"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Azonosítókulcs birtokában nincs szükség összetett jelszavak létrehozására vagy megjegyzésére"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Az azonosítókulcsok olyan digitális kulcsok, amelyeket ujjlenyomata, arca vagy képernyőzár használatával hoz létre"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Az azonosítókulcsokat a rendszer jelszókezelőbe menti, így más eszközökbe is be tud jelentkezni"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Válassza ki a(z) <xliff:g id="CREATETYPES">%1$s</xliff:g> helyét"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"azonosítókulcsok létrehozása"</string>
- <string name="save_your_password" msgid="6597736507991704307">"jelszó mentése"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"bejelentkezési adatok mentése"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Jelszókezelő kiválasztásával mentheti a saját adatokat, és gyorsabban jelentkezhet be a következő alkalommal."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Létrehoz azonosítókulcsot a következőhöz: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Szeretné elmenteni a(z) <xliff:g id="APPNAME">%1$s</xliff:g> jelszavát?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Menti a bejelentkezési adatokat a következőhöz: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"A(z) <xliff:g id="APPDOMAINNAME">%1$s</xliff:g>-<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> bármilyen eszközön használható. A(z) <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> szolgáltatásba van mentve a következő számára: <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"azonosítókulcs"</string>
<string name="password" msgid="6738570945182936667">"jelszó"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"bejelentkezési adatok"</string>
<string name="sign_in_info" msgid="2627704710674232328">"bejelentkezési adatok"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> mentése ide:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Létrehoz azonosítókulcsot egy másik eszközön?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Szeretné a következőt használni az összes bejelentkezési adatához: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ez a jelszókezelő a bejelentkezés megkönnyítése érdekében tárolja jelszavait és azonosítókulcsait."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Beállítás alapértelmezettként"</string>
<string name="use_once" msgid="9027366575315399714">"Egyszeri használat"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> jelszó, <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> azonosítókulcs"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index d5d1217..782b2d9 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Չեղարկել"</string>
<string name="string_continue" msgid="1346732695941131882">"Շարունակել"</string>
<string name="string_more_options" msgid="7990658711962795124">"Այլ տարբերակներ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Ստեղծել այլ տեղում"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Պահել այլ տեղում"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Օգտագործել այլ սարք"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Պահել մեկ այլ սարքում"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Անցաբառերի հետ ավելի ապահով է"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Անցաբառերի շնորհիվ դուք բարդ գաղտնաբառեր ստեղծելու կամ հիշելու անհրաժեշտություն չեք ունենա"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Անցաբառերը գաղտնագրված թվային բանալիներ են, որոնք ստեղծվում են մատնահետքի, դեմքով ապակողպման կամ էկրանի կողպման օգտագործմամբ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Դուք կարող եք մուտք գործել այլ սարքերում, քանի որ անցաբառերը պահվում են գաղտնաբառերի կառավարիչում"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Ընտրեք, թե որտեղ <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ստեղծել ձեր անցաբառերը"</string>
- <string name="save_your_password" msgid="6597736507991704307">"պահել գաղտնաբառը"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"պահել մուտքի տվյալները"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Ընտրեք գաղտնաբառերի կառավարիչ՝ ձեր տեղեկությունները պահելու և հաջորդ անգամ ավելի արագ մուտք գործելու համար։"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Ստեղծե՞լ անցաբառ «<xliff:g id="APPNAME">%1$s</xliff:g>» հավելվածի համար"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Պահե՞լ «<xliff:g id="APPNAME">%1$s</xliff:g>» հավելվածի գաղտնաբառը"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Պահե՞լ «<xliff:g id="APPNAME">%1$s</xliff:g>» հավելվածի մուտքի տվյալները"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Դուք կարող եք «<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>» հավելվածի ձեր <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>ն օգտագործել ցանկացած սարքում։ Այն պահված է «<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>» հավելվածում <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>-ի համար։"</string>
<string name="passkey" msgid="632353688396759522">"անցաբառ"</string>
<string name="password" msgid="6738570945182936667">"գաղտնաբառ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Ստեղծե՞լ անցաբառ մեկ այլ սարքում"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Միշտ մուտք գործե՞լ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> հավելվածի միջոցով"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Գաղտնաբառերի այս կառավարիչը կպահի ձեր գաղտնաբառերն ու անցաբառերը՝ օգնելու ձեզ հեշտությամբ մուտք գործել հաշիվ։"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Նշել որպես կանխադրված"</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>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index 69f2177..f16a321 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Batal"</string>
<string name="string_continue" msgid="1346732695941131882">"Lanjutkan"</string>
<string name="string_more_options" msgid="7990658711962795124">"Opsi lainnya"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Buat di tempat lain"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Simpan ke tempat lain"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Gunakan perangkat lain"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Simpan ke perangkat lain"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih aman dengan kunci sandi"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dengan kunci sandi, Anda tidak perlu membuat atau mengingat sandi yang rumit"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci sandi adalah kunci digital terenkripsi yang Anda buat menggunakan sidik jari, wajah, atau kunci layar"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Kunci sandi disimpan ke pengelola sandi, sehingga Anda dapat login di perangkat lainnya"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Pilih tempat untuk <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"membuat kunci sandi Anda"</string>
- <string name="save_your_password" msgid="6597736507991704307">"menyimpan sandi Anda"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"menyimpan info login Anda"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Pilih pengelola sandi untuk menyimpan info Anda dan login lebih cepat pada waktu berikutnya."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Buat kunci sandi untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Simpan sandi untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Simpan info login untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Anda dapat menggunakan <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> di perangkat mana pun. Disimpan ke <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> untuk <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"kunci sandi"</string>
<string name="password" msgid="6738570945182936667">"sandi"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"login"</string>
<string name="sign_in_info" msgid="2627704710674232328">"info login"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Simpan <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ke"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Buat kunci sandi di perangkat lain?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Gunakan <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> untuk semua info login Anda?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Pengelola sandi ini akan menyimpan sandi dan kunci sandi untuk membantu Anda login dengan mudah."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Setel sebagai default"</string>
<string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> sandi • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci sandi"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index fc0ca94..170cd9a 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Hætta við"</string>
<string name="string_continue" msgid="1346732695941131882">"Áfram"</string>
<string name="string_more_options" msgid="7990658711962795124">"Fleiri valkostir"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Búa til annarsstaðar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Vista annarsstaðar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Nota annað tæki"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Vista í öðru tæki"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Aukið öryggi með aðgangslyklum"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Með aðgangslyklum þarftu hvorki að búa til né muna flókin aðgangsorð"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Aðgangslyklar eru dulkóðaðir stafrænir lyklar sem þú býrð til með fingrafarinu þínu, andliti eða skjálás."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Þeir eru vistaðir í aðgangsorðastjórnun svo þú getir skráð þig inn í öðrum tækjum"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Veldu hvar á að <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"búa til aðgangslykla"</string>
- <string name="save_your_password" msgid="6597736507991704307">"vistaðu aðgangsorðið"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"vistaðu innskráningarupplýsingarnar"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Veldu aðgangsorðastjórnun til að vista upplýsingarnar og vera fljótari að skrá þig inn næst."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Viltu búa til aðgangslykil fyrir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Viltu vista aðgangsorð fyrir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Viltu vista innskráningarupplýsingar fyrir <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Þú getur notað <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> í hvaða tæki sem er. Það er vistað á <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> fyrir <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"aðgangslykill"</string>
<string name="password" msgid="6738570945182936667">"aðgangsorð"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"innskráningar"</string>
<string name="sign_in_info" msgid="2627704710674232328">"innskráningarupplýsingar"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Vista <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> í"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Viltu búa til aðgangslykil í öðru tæki?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Nota <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> fyrir allar innskráningar?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Þessi aðgangsorðastjórnun vistar aðgangsorð og aðgangslykla til að auðvelda þér að skrá þig inn."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Stilla sem sjálfgefið"</string>
<string name="use_once" msgid="9027366575315399714">"Nota einu sinni"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> aðgangsorð • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> aðgangslyklar"</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index 00489f5..0707256 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Annulla"</string>
<string name="string_continue" msgid="1346732695941131882">"Continua"</string>
<string name="string_more_options" msgid="7990658711962795124">"Altre opzioni"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Crea in un altro luogo"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Salva in un altro luogo"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usa un altro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Salva su un altro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Più al sicuro con le passkey"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Con le passkey non è necessario creare o ricordare password complesse"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Le passkey sono chiavi digitali criptate che crei usando la tua impronta, il tuo volto o il blocco schermo"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Vengono salvate in un gestore delle password, così potrai accedere su altri dispositivi"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Scegli dove <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"Crea le tue passkey"</string>
- <string name="save_your_password" msgid="6597736507991704307">"salva la password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"salva le tue informazioni di accesso"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Seleziona un gestore delle password per salvare i tuoi dati e accedere più velocemente la prossima volta."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vuoi creare una passkey per <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vuoi salvare la password di <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vuoi salvare i dati di accesso di <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Puoi usare la tua <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> su qualsiasi dispositivo. Questa credenziale viene salvata in <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> per <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"accessi"</string>
<string name="sign_in_info" msgid="2627704710674232328">"dati di accesso"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Salva <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> in"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vuoi creare una passkey su un altro dispositivo?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vuoi usare <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> per tutti gli accessi?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Questo gestore delle password archivierà le password e le passkey per aiutarti ad accedere facilmente."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Imposta come valore predefinito"</string>
<string name="use_once" msgid="9027366575315399714">"Usa una volta"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> password • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> passkey"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index c5201b1..be1af3b 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"ביטול"</string>
<string name="string_continue" msgid="1346732695941131882">"המשך"</string>
<string name="string_more_options" msgid="7990658711962795124">"אפשרויות נוספות"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"יצירה במקום אחר"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"שמירה במקום אחר"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"שימוש במכשיר אחר"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"שמירה במכשיר אחר"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"בטוח יותר להשתמש במפתחות גישה"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"עם מפתחות הגישה לא צריך יותר ליצור או לזכור סיסמאות מורכבות"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"מפתחות גישה הם מפתחות דיגיטליים מוצפנים שניתן ליצור באמצעות טביעת האצבע, זיהוי הפנים או נעילת המסך"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"מפתחות הגישה והסיסמאות נשמרים במנהל הסיסמאות כך שניתן להיכנס לחשבון במכשירים אחרים"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"צריך לבחור לאן <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"יצירת מפתחות גישה"</string>
- <string name="save_your_password" msgid="6597736507991704307">"שמירת הסיסמה שלך"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"שמירת פרטי הכניסה שלך"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"אפשר לבחור באחד משירותי ניהול הסיסמאות כדי לשמור את הפרטים ולהיכנס לחשבון מהר יותר בפעם הבאה."</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="5220979185879006862">"ליצור מפתח גישה ל-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"לשמור את הסיסמה של <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"לשמור את פרטי הכניסה של <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"אפשר להשתמש ב<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> של <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> בכל מכשיר. הוא שמור ב<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> של <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</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="6372952459932674632">"ליצור מפתח גישה במכשיר אחר?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"ליצור מפתח גישה במכשיר אחר?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"להשתמש ב-<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> בכל הכניסות?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"במנהל הסיסמאות הזה יאוחסנו הסיסמאות ומפתחות הגישה שלך, כדי לעזור לך להיכנס לחשבון בקלות."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"במנהל הסיסמאות הזה יאוחסנו הסיסמאות ומפתחות הגישה שלך, כדי לעזור לך להיכנס לחשבון בקלות"</string>
<string name="set_as_default" msgid="4415328591568654603">"הגדרה כברירת מחדל"</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>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index 18681fe..9bdb9b0 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"キャンセル"</string>
<string name="string_continue" msgid="1346732695941131882">"続行"</string>
<string name="string_more_options" msgid="7990658711962795124">"その他のオプション"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"別の場所で作成"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"別の場所に保存"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"別のデバイスを使用"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"他のデバイスに保存"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"パスキーでより安全に"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"パスキーがあれば、複雑なパスワードを作成したり覚えたりする必要はありません"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"パスキーは、指紋認証、顔認証、または画面ロックを使って作成される暗号化されたデジタルキーです"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"パスワード マネージャーに保存され、他のデバイスでもログインできます"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> の保存場所の選択"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"パスキーの作成"</string>
- <string name="save_your_password" msgid="6597736507991704307">"パスワードを保存"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ログイン情報を保存"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"パスワード マネージャーを選択して情報を保存しておくと、次回からすばやくログインできます。"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> のパスキーを作成しますか?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> のパスワードを保存しますか?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> のログイン情報を保存しますか?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> の<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>はどのデバイスでも使用できます。<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> の <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>に保存されます。"</string>
<string name="passkey" msgid="632353688396759522">"パスキー"</string>
<string name="password" msgid="6738570945182936667">"パスワード"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"他のデバイスでパスキーを作成しますか?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ログインのたびに <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> を使用しますか?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"このパスワード マネージャーに、パスワードやパスキーが保存され、簡単にログインできるようになります。"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"デフォルトに設定"</string>
<string name="use_once" msgid="9027366575315399714">"1 回使用"</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>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index 72f6d19..5b8398a 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"გაუქმება"</string>
<string name="string_continue" msgid="1346732695941131882">"გაგრძელება"</string>
<string name="string_more_options" msgid="7990658711962795124">"სხვა ვარიანტები"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"სხვა სივრცეში შექმნა"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"სხვა სივრცეში შენახვა"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"სხვა მოწყობილობის გამოყენება"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"სხვა მოწყობილობაზე შენახვა"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"უფრო უსაფრთხოა წვდომის გასაღების შემთხვევაში"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"წვდომის გასაღებების დახმარებით აღარ მოგიწევთ რთული პაროლების შექმნა და დამახსოვრება"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"წვდომის გასაღებები დაშიფრული ციფრული გასაღებებია, რომლებსაც თქვენი თითის ანაბეჭდით, სახით ან ეკრანის დაბლოკვით ქმნით"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ისინი შეინახება პაროლების მმართველში, რათა სხვა მოწყობილობებიდან შესვლაც შეძლოთ"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"აირჩიეთ, სად უნდა <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"შექმენით თქვენი პაროლი"</string>
- <string name="save_your_password" msgid="6597736507991704307">"შეინახეთ თქვენი პაროლი"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"შეინახეთ თქვენი სისტემაში შესვლის ინფორმაცია"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"აირჩიეთ პაროლების მმართველი თქვენი ინფორმაციის შესანახად, რომ მომავალში უფრო სწრაფად შეხვიდეთ."</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="5220979185879006862">"შექმნით წვდომის გასაღებს <xliff:g id="APPNAME">%1$s</xliff:g> აპისთვის?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"შეინახავთ <xliff:g id="APPNAME">%1$s</xliff:g> აპის პაროლს?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"შეინახავთ <xliff:g id="APPNAME">%1$s</xliff:g> აპში შესვლის ინფორმაციას?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"შეგიძლიათ გამოიყენოთ თქვენი <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ნებისმიერ მოწყობილობაზე. ის შეინახება <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>-ზე <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>-თვის."</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="6372952459932674632">"გსურთ პაროლის შექმნა სხვა მოწყობილობაში?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"გსურთ პაროლის შექმნა სხვა მოწყობილობაში?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"გსურთ, გამოიყენოთ<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> სისტემაში ყველა შესვლისთვის?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"მოცემული პაროლების მმართველი შეინახავს თქვენს პაროლებს და წვდომის გასაღებს, რომლებიც დაგეხმარებათ სისტემაში მარტივად შესვლაში."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"მოცემული პაროლების მმართველი შეინახავს თქვენს პაროლებს და წვდომის გასაღებს, რომლებიც დაგეხმარებათ სისტემაში მარტივად შესვლაში."</string>
<string name="set_as_default" msgid="4415328591568654603">"ნაგულისხმევად დაყენება"</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>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 5d1bb93..bf58b21 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Бас тарту"</string>
<string name="string_continue" msgid="1346732695941131882">"Жалғастыру"</string>
<string name="string_more_options" msgid="7990658711962795124">"Басқа опциялар"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Басқа орында жасау"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Басқа орынға сақтау"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Басқа құрылғыны пайдалану"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Басқа құрылғыға сақтау"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Кіру кілттерімен қауіпсіздеу"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Кіру кілттері бар кезде күрделі құпия сөздер жасаудың немесе оларды есте сақтаудың қажеті жоқ."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Кіру кілттері — саусақ ізі, бет не экран құлпы арқылы жасалатын шифрланған цифрлық кілттер."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Олар құпия сөз менеджеріне сақталады. Соның арқасында басқа құрылғылардан кіре аласыз."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> таңдау"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"кіру кілттерін жасаңыз"</string>
- <string name="save_your_password" msgid="6597736507991704307">"құпия сөзді сақтау"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"тіркелу деректерін сақтау"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Мәліметіңізді сақтап, келесіде жылдам кіру үшін құпия сөз менеджерін таңдаңыз."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін кіру кілтін жасау керек пе?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін құпия сөзді сақтау керек пе?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> үшін кіру мәліметін сақтау керек пе?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> кез келген құрылғыда пайдаланыла алады. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> үшін ол <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> қызметінде сақталады."</string>
<string name="passkey" msgid="632353688396759522">"кіру кілті"</string>
<string name="password" msgid="6738570945182936667">"құпия сөз"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Кіру кілті басқа құрылғыда жасалсын ба?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Барлық кіру әрекеті үшін <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> пайдаланылсын ба?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Аккаунтқа оңай кіру үшін құпия сөз менеджері құпия сөздер мен кіру кілттерін сақтайды."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Әдепкі етіп орнату"</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>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index 1edc795..1966aa1 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"បោះបង់"</string>
<string name="string_continue" msgid="1346732695941131882">"បន្ត"</string>
<string name="string_more_options" msgid="7990658711962795124">"ជម្រើសច្រើនទៀត"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"បង្កើតនៅកន្លែងផ្សេងទៀត"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"រក្សាទុកក្នុងកន្លែងផ្សេងទៀត"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ប្រើឧបករណ៍ផ្សេងទៀត"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"រក្សាទុកទៅក្នុងឧបករណ៍ផ្សេង"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"កាន់តែមានសុវត្ថិភាពដោយប្រើកូដសម្ងាត់"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"តាមរយៈកូដសម្ងាត់ អ្នកមិនចាំបាច់បង្កើត ឬចងចាំពាក្យសម្ងាត់ស្មុគស្មាញនោះទេ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"កូដសម្ងាត់ត្រូវបានអ៊ីនគ្រីបឃីឌីជីថលដែលអ្នកបង្កើតដោយប្រើស្នាមម្រាមដៃ មុខ ឬចាក់សោអេក្រង់របស់អ្នក"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"កូដសម្ងាត់ត្រូវបានរក្សាទុកទៅក្នុងកម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ ដូច្នេះអ្នកអាចចូលនៅលើឧបករណ៍ផ្សេងទៀត"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"ជ្រើសរើសកន្លែងដែលត្រូវ <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"បង្កើតកូដសម្ងាត់របស់អ្នក"</string>
- <string name="save_your_password" msgid="6597736507991704307">"រក្សាទុកពាក្យសម្ងាត់របស់អ្នក"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"រក្សាទុកព័ត៌មានចូលគណនីរបស់អ្នក"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ជ្រើសរើសកម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់ ដើម្បីរក្សាទុកព័ត៌មានរបស់អ្នក និងចូលគណនីបានលឿនជាងមុនលើកក្រោយ។"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"បង្កើតកូដសម្ងាត់សម្រាប់ <xliff:g id="APPNAME">%1$s</xliff:g> ឬ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"រក្សាទុកពាក្យសម្ងាត់សម្រាប់ <xliff:g id="APPNAME">%1$s</xliff:g> ឬ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"រក្សាទុកព័ត៌មានអំពីការចូលគណនីសម្រាប់ <xliff:g id="APPNAME">%1$s</xliff:g> ឬ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"អ្នកអាចប្រើ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> របស់អ្នកនៅលើឧបករណ៍ណាក៏បាន។ វាត្រូវបានរក្សាទុកក្នុង <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> សម្រាប់ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>។"</string>
<string name="passkey" msgid="632353688396759522">"កូដសម្ងាត់"</string>
<string name="password" msgid="6738570945182936667">"ពាក្យសម្ងាត់"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"បង្កើតកូដសម្ងាត់នៅក្នុងឧបករណ៍ផ្សេងទៀតឬ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ប្រើ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> សម្រាប់ការចូលគណនីទាំងអស់របស់អ្នកឬ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"កម្មវិធីគ្រប់គ្រងពាក្យសម្ងាត់នេះនឹងរក្សាទុកពាក្យសម្ងាត់ និងកូដសម្ងាត់របស់អ្នក ដើម្បីជួយឱ្យអ្នកចូលគណនីបានយ៉ាងងាយស្រួល។"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"កំណត់ជាលំនាំដើម"</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>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index cac0a67..cfc1098 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ರದ್ದುಗೊಳಿಸಿ"</string>
<string name="string_continue" msgid="1346732695941131882">"ಮುಂದುವರಿಸಿ"</string>
<string name="string_more_options" msgid="7990658711962795124">"ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"ಮತ್ತೊಂದು ಸ್ಥಳದಲ್ಲಿ ರಚಿಸಿ"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ಮತ್ತೊಂದು ಸ್ಥಳದಲ್ಲಿ ಉಳಿಸಿ"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ಬೇರೊಂದು ಸಾಧನವನ್ನು ಬಳಸಿ"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ಬೇರೊಂದು ಸಾಧನದಲ್ಲಿ ಉಳಿಸಿ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ಪಾಸ್ಕೀಗಳೊಂದಿಗೆ ಸುರಕ್ಷಿತವಾಗಿರುತ್ತವೆ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ಪಾಸ್ಕೀಗಳ ಮೂಲಕ, ನೀವು ಕ್ಲಿಷ್ಟ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ರಚಿಸುವ ಅಥವಾ ನೆನಪಿಟ್ಟುಕೊಳ್ಳುವ ಅಗತ್ಯವಿಲ್ಲ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ಪಾಸ್ಕೀಗಳು ನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್, ಫೇಸ್ ಅಥವಾ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ನೀವು ರಚಿಸುವ ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡಿಜಿಟಲ್ ಕೀಗಳಾಗಿವೆ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ಅವುಗಳನ್ನು ಪಾಸ್ವರ್ಡ್ ನಿರ್ವಾಹಕದಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ, ಹಾಗಾಗಿ ನೀವು ಇತರ ಸಾಧನಗಳಲ್ಲಿ ಸೈನ್ ಇನ್ ಮಾಡಬಹುದು"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> ಅನ್ನು ಎಲ್ಲಿ ಉಳಿಸಬೇಕು ಎಂದು ಆಯ್ಕೆಮಾಡಿ"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ನಿಮ್ಮ ಪಾಸ್ಕೀಗಳನ್ನು ರಚಿಸಿ"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ ಉಳಿಸಿ"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ನಿಮ್ಮ ಸೈನ್-ಇನ್ ಮಾಹಿತಿ ಉಳಿಸಿ"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು ಉಳಿಸಲು ಪಾಸ್ವರ್ಡ್ ನಿರ್ವಾಹಕವನ್ನು ಆಯ್ಕೆಮಾಡಿ ಹಾಗೂ ಮುಂದಿನ ಬಾರಿ ವೇಗವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡಿ."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ಗಾಗಿ ಪಾಸ್ಕೀ ಅನ್ನು ರಚಿಸುವುದೇ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> ಗಾಗಿ ಪಾಸ್ವರ್ಡ್ ಉಳಿಸುವುದೇ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> ಗಾಗಿ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಉಳಿಸುವುದೇ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"ನೀವು ಯಾವುದೇ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ಅನ್ನು ಬಳಸಬಹುದು. ಇದನ್ನು <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> ಗಾಗಿ <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ಗೆ ಉಳಿಸಲಾಗಿದೆ."</string>
<string name="passkey" msgid="632353688396759522">"ಪಾಸ್ಕೀ"</string>
<string name="password" msgid="6738570945182936667">"ಪಾಸ್ವರ್ಡ್"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"ಮತ್ತೊಂದು ಸಾಧನದಲ್ಲಿ ಪಾಸ್ಕೀ ರಚಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ನಿಮ್ಮ ಎಲ್ಲಾ ಸೈನ್-ಇನ್ಗಳಿಗಾಗಿ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ಅನ್ನು ಬಳಸುವುದೇ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ಈ ಪಾಸ್ವರ್ಡ್ ನಿರ್ವಾಹಕವು ನಿಮಗೆ ಸುಲಭವಾಗಿ ಸೈನ್ ಇನ್ ಮಾಡುವುದಕ್ಕೆ ಸಹಾಯ ಮಾಡಲು ನಿಮ್ಮ ಪಾಸ್ವರ್ಡ್ಗಳು ಮತ್ತು ಪಾಸ್ಕೀಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ಡೀಫಾಲ್ಟ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ"</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>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 0902797..ed53a6c 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"취소"</string>
<string name="string_continue" msgid="1346732695941131882">"계속"</string>
<string name="string_more_options" msgid="7990658711962795124">"옵션 더보기"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"다른 위치에 만들기"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"다른 위치에 저장"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"다른 기기 사용"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"다른 기기에 저장"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"패스키로 더 안전하게"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"패스키를 사용하면 복잡한 비밀번호를 만들거나 기억하지 않아도 됩니다."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"패스키는 지문, 얼굴 또는 화면 잠금으로 생성하는 암호화된 디지털 키입니다."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"비밀번호 관리자에 저장되므로 다른 기기에서 로그인할 수 있습니다."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> 작업을 위한 위치 선택"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"패스키 만들기"</string>
- <string name="save_your_password" msgid="6597736507991704307">"비밀번호 저장"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"로그인 정보 저장"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"정보를 저장해서 다음에 더 빠르게 로그인하려면 비밀번호 관리자를 선택하세요."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>의 패스키를 만드시겠습니까?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g>의 비밀번호를 저장하시겠습니까?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g>의 로그인 정보를 저장하시겠습니까?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"기기에서 <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>을(를) 사용할 수 있습니다. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>을(를) 위해 <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>에 저장되어 있습니다."</string>
<string name="passkey" msgid="632353688396759522">"패스키"</string>
<string name="password" msgid="6738570945182936667">"비밀번호"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"다른 기기에서 패스키를 만들까요?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"모든 로그인에 <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>을(를) 사용하시겠습니까?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"이 비밀번호 관리자는 비밀번호와 패스키를 저장하여 사용자가 간편하게 로그인하도록 돕습니다."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"기본값으로 설정"</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>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 5bc4924..68ce3c7 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Жок"</string>
<string name="string_continue" msgid="1346732695941131882">"Улантуу"</string>
<string name="string_more_options" msgid="7990658711962795124">"Башка варианттар"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Башка жерде түзүү"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Башка жерге сактоо"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Башка түзмөк колдонуу"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Башка түзмөккө сактоо"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Мүмкүндүк алуу ачкычтары менен коопсузураак болот"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Мүмкүндүк алуу ачкычтары менен татаал сырсөздөрдү түзүп же эстеп калуунун кереги жок"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Мүмкүндүк алуу ачкычтары – манжаңыздын изи, жүзүңүз же экранды кулпулоо функциясы аркылуу түзгөн шифрленген санариптик ачкычтар"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Алар сырсөздөрдү башкаргычка сакталып, аккаунтуңузга башка түзмөктөрдөн кире аласыз"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> үчүн жер тандаңыз"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"мүмкүндүк алуу ачкычтарын түзүү"</string>
- <string name="save_your_password" msgid="6597736507991704307">"сырсөзүңүздү сактаңыз"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"кирүү маалыматын сактаңыз"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Маалыматыңызды сактоо жана кийинки жолу тезирээк кирүү үчүн сырсөздөрдү башкаргычты тандаңыз."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн мүмкүндүк алуу ачкычын түзөсүзбү?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн сырсөз сакталсынбы?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> үчүн кирүү маалыматы сакталсынбы?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> каалаган түзмөктө колдонулат. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> маалыматы <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> колдонмосунда сакталат."</string>
<string name="passkey" msgid="632353688396759522">"мүмкүндүк алуу ачкычы"</string>
<string name="password" msgid="6738570945182936667">"сырсөз"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Мүмкүндүк алуу ачкычы башка түзмөктө түзүлсүнбү?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> бардык аккаунттарга кирүү үчүн колдонулсунбу?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Сырсөздөрүңүздү жана ачкычтарыңызды Сырсөздөрдү башкаргычка сактап коюп, каалаган убакта колдоно берсеңиз болот."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Демейки катары коюу"</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>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 72968ea..9814521 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ຍົກເລີກ"</string>
<string name="string_continue" msgid="1346732695941131882">"ສືບຕໍ່"</string>
<string name="string_more_options" msgid="7990658711962795124">"ຕົວເລືອກເພີ່ມເຕີມ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"ສ້າງໃນບ່ອນອື່ນ"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ບັນທຶກໃສ່ບ່ອນອື່ນ"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ໃຊ້ອຸປະກອນອື່ນ"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ບັນທຶກໃສ່ອຸປະກອນອື່ນ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ປອດໄພຂຶ້ນດ້ວຍກະແຈຜ່ານ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ໂດຍການໃຊ້ກະແຈຜ່ານ, ທ່ານບໍ່ຈຳເປັນຕ້ອງສ້າງ ຫຼື ຈື່ລະຫັດຜ່ານທີ່ຊັບຊ້ອນ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ກະແຈຜ່ານແມ່ນກະແຈດິຈິຕອນທີ່ໄດ້ຖືກເຂົ້າລະຫັດໄວ້ເຊິ່ງທ່ານສ້າງຂຶ້ນໂດຍໃຊ້ລາຍນິ້ວມື, ໃບໜ້າ ຫຼື ການລັອກໜ້າຈໍຂອງທ່ານ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ພວກມັນຖືກບັນທຶກໄວ້ຢູ່ໃນຕົວຈັດການລະຫັດຜ່ານ, ດັ່ງນັ້ນທ່ານສາມາດເຂົ້າສູ່ລະບົບຢູ່ອຸປະກອນອື່ນໆໄດ້"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"ເລືອກບ່ອນທີ່ຈະ <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ສ້າງກະແຈຜ່ານຂອງທ່ານ"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ບັນທຶກລະຫັດຜ່ານຂອງທ່ານ"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ບັນທຶກຂໍ້ມູນການເຂົ້າສູ່ລະບົບຂອງທ່ານ"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ເລືອກຕົວຈັດການລະຫັດຜ່ານເພື່ອບັນທຶກຂໍ້ມູນຂອງທ່ານ ແລະ ເຂົ້າສູ່ລະບົບໄວຂຶ້ນໃນເທື່ອຕໍ່ໄປ."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ສ້າງກະແຈຜ່ານສຳລັບ <xliff:g id="APPNAME">%1$s</xliff:g> ບໍ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"ບັນທຶກລະຫັດຜ່ານສຳລັບ <xliff:g id="APPNAME">%1$s</xliff:g> ບໍ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"ບັນທຶກຂໍ້ມູນການເຂົ້າສູ່ລະບົບສຳລັບ <xliff:g id="APPNAME">%1$s</xliff:g> ບໍ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"ທ່ານສາມາດໃຊ້ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ຂອງທ່ານຢູ່ອຸປະກອນໃດກໍໄດ້. ມັນຈະຖືກບັນທຶກໃສ່ <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ສຳລັບ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"ກະແຈຜ່ານ"</string>
<string name="password" msgid="6738570945182936667">"ລະຫັດຜ່ານ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"ສ້າງກະແຈຜ່ານໃນອຸປະກອນອື່ນບໍ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ໃຊ້ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ສຳລັບການເຂົ້າສູ່ລະບົບທັງໝົດຂອງທ່ານບໍ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ຕົວຈັດການລະຫັດຜ່ານນີ້ຈະຈັດເກັບລະຫັດຜ່ານ ແລະ ກະແຈຜ່ານຂອງທ່ານໄວ້ເພື່ອຊ່ວຍໃຫ້ທ່ານເຂົ້າສູ່ລະບົບໄດ້ໂດຍງ່າຍ."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ຕັ້ງເປັນຄ່າເລີ່ມຕົ້ນ"</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>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index bcebd79..5ec68bb 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Atšaukti"</string>
<string name="string_continue" msgid="1346732695941131882">"Tęsti"</string>
<string name="string_more_options" msgid="7990658711962795124">"Daugiau parinkčių"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Sukurti kitoje vietoje"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Išsaugoti kitoje vietoje"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Naudoti kitą įrenginį"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Išsaugoti kitame įrenginyje"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Saugiau naudojant slaptažodžius"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Naudojant „passkey“ nereikės kurti ir prisiminti sudėtingų slaptažodžių"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"„Passkey“ šifruojami skaitiniais raktais, kuriuos sukuriate naudodami piršto atspaudą, veidą ar ekrano užraktą"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Jie saugomi slaptažodžių tvarkyklėje, kad galėtumėte prisijungti kituose įrenginiuose"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Pasirinkite, kur <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"kurkite slaptažodžius"</string>
- <string name="save_your_password" msgid="6597736507991704307">"išsaugoti slaptažodį"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"išsaugoti prisijungimo informaciją"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Pasirinkite slaptažodžių tvarkyklę, kurią naudodami galėsite išsaugoti informaciją ir kitą kartą prisijungti greičiau."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Sukurti „passkey“, skirtą „<xliff:g id="APPNAME">%1$s</xliff:g>“?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Išsaugoti „<xliff:g id="APPNAME">%1$s</xliff:g>“ slaptažodį?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Išsaugoti prisijungimo prie „<xliff:g id="APPNAME">%1$s</xliff:g>“ informaciją?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Galite naudoti „<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>“ <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> bet kuriame įrenginyje. Jis išsaugomas šioje sistemoje: <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> (<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>)"</string>
<string name="passkey" msgid="632353688396759522">"„passkey“"</string>
<string name="password" msgid="6738570945182936667">"slaptažodis"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"prisijungimo informacija"</string>
<string name="sign_in_info" msgid="2627704710674232328">"prisijungimo informaciją"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Išsaugoti <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Sukurti slaptažodį kitame įrenginyje?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Naudoti <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> visada prisijungiant?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Šioje slaptažodžių tvarkyklėje bus saugomi jūsų slaptažodžiai, kad galėtumėte lengvai prisijungti."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Nustatyti kaip numatytąjį"</string>
<string name="use_once" msgid="9027366575315399714">"Naudoti vieną kartą"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Slaptažodžių: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • „Passkey“: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index b0ffe40..71ab864 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Atcelt"</string>
<string name="string_continue" msgid="1346732695941131882">"Turpināt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Citas opcijas"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Izveidot citur"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Saglabāt citur"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Izmantot citu ierīci"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Saglabāt citā ierīcē"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lielāka drošība ar piekļuves atslēgām"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Izmantojot piekļuves atslēgas, nav jāveido vai jāatceras sarežģītas paroles."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Piekļuves atslēgas ir šifrētas digitālas atslēgas, ko varat izveidot, izmantojot pirksta nospiedumu, seju vai ekrāna bloķēšanas informāciju."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Tās tiek saglabātas paroļu pārvaldniekā, lai jūs varētu pierakstīties citās ierīcēs."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Izvēlieties, kur: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"veidot piekļuves atslēgas"</string>
- <string name="save_your_password" msgid="6597736507991704307">"saglabāt paroli"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"saglabāt pierakstīšanās informāciju"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Lai saglabātu informāciju un nākamreiz varētu pierakstīties ātrāk, atlasiet paroļu pārvaldnieku."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vai izveidot piekļuves atslēgu lietotnei <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vai saglabāt paroli lietotnei <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vai saglabāt pierakstīšanās informāciju lietotnei <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> — to varat izmantot jebkurā ierīcē. Šī informācija tiek saglabāta pakalpojumā <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ar kontu <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"piekļuves atslēga"</string>
<string name="password" msgid="6738570945182936667">"parole"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"pierakstīšanās informācija"</string>
<string name="sign_in_info" msgid="2627704710674232328">"pierakstīšanās informācija"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Kur jāsaglabā <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vai izveidot piekļuves atslēgu citā ierīcē?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vai vienmēr izmantot <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>, lai pierakstītos?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Šis paroļu pārvaldnieks glabās jūsu paroles un piekļuves atslēgas, lai atvieglotu pierakstīšanos."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Iestatīt kā noklusējumu"</string>
<string name="use_once" msgid="9027366575315399714">"Izmantot vienreiz"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Paroļu skaits: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Piekļuves atslēgu skaits: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index ea9750b8..ae7473f 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Откажи"</string>
<string name="string_continue" msgid="1346732695941131882">"Продолжи"</string>
<string name="string_more_options" msgid="7990658711962795124">"Повеќе опции"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Создајте на друго место"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Зачувајте на друго место"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Употребете друг уред"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Зачувајте на друг уред"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Побезбедно со криптографски клучеви"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Со криптографските клучеви нема потреба да создавате или да помните сложени лозинки"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Криптографските клучеви се шифрирани дигитални клучеви што ги создавате со вашиот отпечаток, лик или заклучување екран"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Се зачувуваат во управник со лозинки за да може да се најавувате на други уреди"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Изберете каде да <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"создајте криптографски клучеви"</string>
- <string name="save_your_password" msgid="6597736507991704307">"се зачува лозинката"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"се зачуваат податоците за најавување"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Изберете управник со лозинки за да ги зачувате податоците и да се најавите побрзо следниот пат."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Изберете каде да ги зачувате вашите <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Изберете Password Manager за да ги зачувате вашите податоци и да се најавите побрзо следниот пат"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Да се создаде криптографски клуч за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Дали да се зачува лозинката за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Да се зачуваат податоците за најавување за <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Може да го користите вашиот <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> за <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> на секој уред. Зачуван е во <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> за <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</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="6372952459932674632">"Да се создаде криптографски клуч во друг уред?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Да се создаде криптографски клуч во друг уред?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Да се користи <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> за сите ваши најавувања?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Овој управник со лозинки ќе ги складира вашите лозинки и криптографски клучеви за да ви помогне лесно да се најавите."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Овој Password Manager ќе ги складира вашите лозинки и криптографски клучеви за да ви помогне лесно да се најавите"</string>
<string name="set_as_default" msgid="4415328591568654603">"Постави како стандардна опција"</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>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index 37c02a9..4075e69 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"റദ്ദാക്കുക"</string>
<string name="string_continue" msgid="1346732695941131882">"തുടരുക"</string>
<string name="string_more_options" msgid="7990658711962795124">"കൂടുതൽ ഓപ്ഷനുകൾ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"മറ്റൊരു സ്ഥലത്ത് സൃഷ്ടിക്കുക"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"മറ്റൊരു സ്ഥലത്തേക്ക് സംരക്ഷിക്കുക"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"മറ്റൊരു ഉപകരണം ഉപയോഗിക്കുക"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"മറ്റൊരു ഉപകരണത്തിലേക്ക് സംരക്ഷിക്കുക"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"പാസ്കീകൾ ഉപയോഗിച്ച് സുരക്ഷിതരാകൂ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"പാസ്കീകൾ ഉപയോഗിക്കുമ്പോൾ നിങ്ങൾ സങ്കീർണ്ണമായ പാസ്വേഡുകൾ സൃഷ്ടിക്കുകയോ ഓർമ്മിക്കുകയോ ചെയ്യേണ്ടതില്ല"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ഫിംഗർപ്രിന്റ്, മുഖം അല്ലെങ്കിൽ സ്ക്രീൻ ലോക്ക് ഉപയോഗിച്ച് നിങ്ങൾ സൃഷ്ടിക്കുന്ന എൻക്രിപ്റ്റ് ചെയ്ത ഡിജിറ്റൽ കീകളാണ് പാസ്കീകൾ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"അവ ഒരു പാസ്വേഡ് മാനേജറിൽ സംരക്ഷിക്കുന്നതിനാൽ നിങ്ങൾക്ക് മറ്റ് ഉപകരണങ്ങളിലും സൈൻ ഇൻ ചെയ്യാം"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"എവിടെ <xliff:g id="CREATETYPES">%1$s</xliff:g> എന്ന് തിരഞ്ഞെടുക്കുക"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"നിങ്ങളുടെ പാസ്കീകൾ സൃഷ്ടിക്കുക"</string>
- <string name="save_your_password" msgid="6597736507991704307">"നിങ്ങളുടെ പാസ്വേഡ് സംരക്ഷിക്കുക"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"നിങ്ങളുടെ സൈൻ ഇൻ വിവരങ്ങൾ സംരക്ഷിക്കുക"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"നിങ്ങളുടെ വിവരങ്ങൾ സംരക്ഷിക്കാനും അടുത്ത തവണ വേഗത്തിൽ സൈൻ ഇൻ ചെയ്യാനും ഒരു പാസ്വേഡ് മാനേജർ തിരഞ്ഞെടുക്കുക."</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="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്നതിനായി പാസ്കീ സൃഷ്ടിക്കണോ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്നതിനായി പാസ്വേഡ് സംരക്ഷിക്കണോ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്നതിനായി സൈൻ ഇൻ വിവരങ്ങൾ സംരക്ഷിക്കണോ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"നിങ്ങളുടെ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ഏത് ഉപകരണത്തിലും നിങ്ങൾക്ക് ഉപയോഗിക്കാം. ഇത് <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> എന്ന വിലാസത്തിനായി <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിച്ചു."</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="6372952459932674632">"മറ്റൊരു ഉപകരണത്തിൽ പാസ്കീ സൃഷ്ടിക്കണോ?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"മറ്റൊരു ഉപകരണത്തിൽ പാസ്കീ സൃഷ്ടിക്കണോ?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"നിങ്ങളുടെ എല്ലാ സൈൻ ഇന്നുകൾക്കും <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ഉപയോഗിക്കണോ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"എളുപ്പത്തിൽ സൈൻ ഇൻ ചെയ്യാൻ സഹായിക്കുന്നതിന് ഈ പാസ്വേഡ് മാനേജർ നിങ്ങളുടെ പാസ്വേഡുകളും പാസ്കീകളും സംഭരിക്കും."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"എളുപ്പത്തിൽ സൈൻ ഇൻ ചെയ്യാൻ സഹായിക്കുന്നതിന് ഈ Password Manager നിങ്ങളുടെ പാസ്വേഡുകളും പാസ്കീകളും സംഭരിക്കും"</string>
<string name="set_as_default" msgid="4415328591568654603">"ഡിഫോൾട്ടായി സജ്ജീകരിക്കുക"</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>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index 5817ce7..0ac9ce8 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Цуцлах"</string>
<string name="string_continue" msgid="1346732695941131882">"Үргэлжлүүлэх"</string>
<string name="string_more_options" msgid="7990658711962795124">"Бусад сонголт"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Өөр газар үүсгэх"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Өөр газар хадгалах"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Өөр төхөөрөмж ашиглах"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Өөр төхөөрөмжид хадгалах"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Passkey-тэй байхад илүү аюулгүй"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Passkey-н тусламжтай та нарийн төвөгтэй нууц үг үүсгэх эсвэл санах шаардлагагүй"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Passkey нь таны хурууны хээ, царай эсвэл дэлгэцийн түгжээгээ ашиглан үүсгэсэн шифрлэгдсэн дижитал түлхүүр юм"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Тэдгээрийг нууц үгний менежерт хадгалдаг бөгөөд ингэснээр та бусад төхөөрөмжид нэвтрэх боломжтой"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Хаана <xliff:g id="CREATETYPES">%1$s</xliff:g>-г сонгоно уу"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"passkey-үүдээ үүсгэнэ үү"</string>
- <string name="save_your_password" msgid="6597736507991704307">"нууц үгээ хадгалах"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"нэвтрэх мэдээллээ хадгалах"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Мэдээллээ хадгалахын тулд нууц үгний менежер сонгож, дараагийн удаа илүү хурдан нэвтрээрэй."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g>-д passkey үүсгэх үү?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g>-н нууц үгийг хадгалах уу?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g>-н нэвтрэх мэдээллийг хадгалах уу?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Та өөрийн <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>-г дурын төхөөрөмжид ашиглах боломжтой. Үүнийг <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>-д <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>-д зориулж хадгалсан."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"нууц үг"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Өөр төхөөрөмжид passkey үүсгэх үү?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>-г бүх нэвтрэлтдээ ашиглах уу?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Танд хялбархан нэвтрэхэд туслахын тулд энэ нууц үгний менежер таны нууц үг болон passkey-г хадгална."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Өгөгдмөлөөр тохируулах"</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> passkey"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index 0b4b55e..ab69307 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"रद्द करा"</string>
<string name="string_continue" msgid="1346732695941131882">"पुढे सुरू ठेवा"</string>
<string name="string_more_options" msgid="7990658711962795124">"आणखी पर्याय"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"दुसऱ्या ठिकाणी तयार करा"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"दुसऱ्या ठिकाणी सेव्ह करा"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"दुसरे डिव्हाइस वापरा"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"दुसऱ्या डिव्हाइसवर सेव्ह करा"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीसह आणखी सुरक्षित"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"पासकीसोबत, तुम्हाला क्लिष्ट पासवर्ड तयार करण्याची किंवा लक्षात ठेवण्याची आवश्यकता नाही"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी या तुम्ही तुमचे फिंगरप्रिंट, फेस किंवा स्क्रीन लॉक वापरून तयार करता अशा एंक्रिप्ट केलेल्या डिजिटल की आहेत"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"त्या Password Manager मध्ये सेव्ह केलेल्या असतात, जेणेकरून तुम्ही इतर डिव्हाइसवर साइन इन करू शकाल"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> कुठे करायचे ते निवडा"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"तुमच्या पासकी तयार करा"</string>
- <string name="save_your_password" msgid="6597736507991704307">"तुमचा पासवर्ड सेव्ह करा"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"तुमची साइन-इन माहिती सेव्ह करा"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"तुमची माहिती सेव्ह करण्यासाठी आणि पुढच्या वेळी जलद साइन इन करण्याकरिता Password Manager निवडा."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> साठी पासकी तयार करायची का?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> साठी पासवर्ड सेव्ह करायचा का?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> साठी साइन-इन माहिती सेव्ह करायची का?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"तुम्ही कोणत्याही डिव्हाइसवर तुमचे <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> वापरू शकता. ते <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> साठी <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> वर सेव्ह केले जाते."</string>
<string name="passkey" msgid="632353688396759522">"पासकी"</string>
<string name="password" msgid="6738570945182936667">"पासवर्ड"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"दुसऱ्या डिव्हाइसमध्ये पासकी तयार करायची आहे का?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"तुमच्या सर्व साइन-इन साठी <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>वापरायचे का?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"तुम्हाला सहजरीत्या साइन इन करण्यात मदत करण्यासाठी हा पासवर्ड व्यवस्थापक तुमचे पासवर्ड आणि पासकी स्टोअर करेल."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"डिफॉल्ट म्हणून सेट करा"</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>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index c6d7e09..d95c3ea 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Batal"</string>
<string name="string_continue" msgid="1346732695941131882">"Teruskan"</string>
<string name="string_more_options" msgid="7990658711962795124">"Lagi pilihan"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Buat di tempat lain"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Simpan di tempat lain"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Gunakan peranti lain"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Simpan kepada peranti lain"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Lebih selamat dengan kunci laluan"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Anda tidak perlu mencipta atau mengingati kata laluan yang rumit dengan kunci laluan"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kunci laluan ialah kunci digital disulitkan yang anda cipta menggunakan cap jari, wajah atau kunci skrin anda"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Kunci laluan disimpan pada password manager supaya anda boleh log masuk pada peranti lain"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Pilih tempat untuk <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"buat kunci laluan anda"</string>
- <string name="save_your_password" msgid="6597736507991704307">"simpan kata laluan anda"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"simpan maklumat log masuk anda"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Pilih password manager untuk menyimpan maklumat anda dan log masuk lebih pantas pada kali seterusnya."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Cipta kunci laluan untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Simpan kata laluan untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Simpan maklumat log masuk untuk <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Anda boleh menggunakan <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> anda pada mana-mana peranti. Ia disimpan pada <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> untuk <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"kunci laluan"</string>
<string name="password" msgid="6738570945182936667">"kata laluan"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"log masuk"</string>
<string name="sign_in_info" msgid="2627704710674232328">"maklumat log masuk"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Simpan <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> pada"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Buat kunci laluan dalam peranti lain?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Gunakan <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> untuk semua log masuk anda?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Pengurus kata laluan ini akan menyimpan kata laluan dan kunci laluan anda untuk membantu anda log masuk dengan mudah."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Tetapkan sebagai lalai"</string>
<string name="use_once" msgid="9027366575315399714">"Gunakan sekali"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> kata laluan • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> kunci laluan"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 4237b00..6630ffa 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"မလုပ်တော့"</string>
<string name="string_continue" msgid="1346732695941131882">"ရှေ့ဆက်ရန်"</string>
<string name="string_more_options" msgid="7990658711962795124">"နောက်ထပ်ရွေးစရာများ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"နောက်တစ်နေရာတွင် ပြုလုပ်ရန်"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"နောက်တစ်နေရာတွင် သိမ်းရန်"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"စက်နောက်တစ်ခု သုံးရန်"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"စက်နောက်တစ်ခုတွင် သိမ်းရန်"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"လျှို့ဝှက်ကီးများဖြင့် ပိုလုံခြုံသည်"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"လျှို့ဝှက်ကီးများဖြင့် ရှုပ်ထွေးသောစကားဝှက်များကို ပြုလုပ်ရန် (သို့) မှတ်မိရန် မလိုပါ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"လျှို့ဝှက်ကီးများမှာ သင်၏လက်ဗွေ၊ မျက်နှာ (သို့) ဖန်သားပြင်လော့ခ်သုံး၍ ပြုလုပ်ထားသော အသွင်ဝှက်ထားသည့် ဒစ်ဂျစ်တယ်ကီးများ ဖြစ်သည်"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"၎င်းတို့ကို စကားဝှက်မန်နေဂျာတွင် သိမ်းသဖြင့် အခြားစက်များတွင် လက်မှတ်ထိုးဝင်နိုင်ပါသည်"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> ရန် နေရာရွေးပါ"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"သင့်လျှို့ဝှက်ကီး ပြုလုပ်ခြင်း"</string>
- <string name="save_your_password" msgid="6597736507991704307">"သင့်စကားဝှက် သိမ်းရန်"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"သင်၏ လက်မှတ်ထိုးဝင်သည့်အချက်အလက်ကို သိမ်းရန်"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"သင်၏အချက်အလက်ကို သိမ်းပြီး နောက်တစ်ကြိမ်၌ ပိုမိုမြန်ဆန်စွာ လက်မှတ်ထိုးဝင်ရန် စကားဝှက်မန်နေဂျာကို ရွေးပါ။"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> အတွက် လျှို့ဝှက်ကီးပြုလုပ်မလား။"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> အတွက် စကားဝှက်ကို သိမ်းမလား။"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> အတွက် လက်မှတ်ထိုးဝင်သည့်အချက်အလက်ကို သိမ်းမလား။"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"မည်သည့်စက်တွင်မဆို သင်၏ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ကို သုံးနိုင်သည်။ ၎င်းကို <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> အတွက် <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> တွင် သိမ်းလိုက်သည်။"</string>
<string name="passkey" msgid="632353688396759522">"လျှို့ဝှက်ကီး"</string>
<string name="password" msgid="6738570945182936667">"စကားဝှက်"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"အခြားစက်တွင် လျှို့ဝှက်ကီးပြုလုပ်မလား။"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"သင်၏လက်မှတ်ထိုးဝင်မှု အားလုံးအတွက် <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> သုံးမလား။"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"သင်အလွယ်တကူ လက်မှတ်ထိုးဝင်နိုင်ရန် ဤစကားဝှက်မန်နေဂျာက စကားဝှက်နှင့် လျှို့ဝှက်ကီးများကို သိမ်းပါမည်။"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"မူရင်းအဖြစ် သတ်မှတ်ရန်"</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>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index 91593d3..34a81e8 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Avbryt"</string>
<string name="string_continue" msgid="1346732695941131882">"Fortsett"</string>
<string name="string_more_options" msgid="7990658711962795124">"Flere alternativer"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Opprett på et annet sted"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Lagre på et annet sted"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Bruk en annen enhet"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Lagre på en annen enhet"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Tryggere med tilgangsnøkler"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med tilgangsnøkler trenger du ikke å lage eller huske kompliserte passord"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Tilgangsnøkler er krypterte digitale nøkler du oppretter med fingeravtrykket, ansiktet eller skjermlåsen"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"De lagres i et verktøy for passordlagring, slik at du kan logge på andre enheter"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Velg hvor <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"opprette tilgangsnøklene dine"</string>
- <string name="save_your_password" msgid="6597736507991704307">"lagre passordet ditt"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"lagre påloggingsinformasjonen din"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Velg et verktøy for passordlagring for å lagre informasjonen din og logge på raskere neste gang."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vil du opprette en tilgangsnøkkel for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vil du lagre passord for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vil du lagre påloggingsinformasjon for <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Du kan bruke <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>-elementet for <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> på alle slags enheter. Det lagres i <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> for <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"tilgangsnøkkel"</string>
<string name="password" msgid="6738570945182936667">"passord"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"pålogginger"</string>
<string name="sign_in_info" msgid="2627704710674232328">"påloggingsinformasjon"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Lagre <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> i"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vil du opprette en tilgangsnøkkel på en annen enhet?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vil du bruke <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> for alle pålogginger?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Dette verktøyet for passordlagring lagrer passord og tilgangsnøkler, så det blir lett å logge på."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Angi som standard"</string>
<string name="use_once" msgid="9027366575315399714">"Bruk én gang"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> passord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> tilgangsnøkler"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index 1324df1..f98ffff9 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"रद्द गर्नुहोस्"</string>
<string name="string_continue" msgid="1346732695941131882">"जारी राख्नुहोस्"</string>
<string name="string_more_options" msgid="7990658711962795124">"थप विकल्पहरू"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"अर्को ठाउँमा बनाउनुहोस्"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"अर्को ठाउँमा सेभ गर्नुहोस्"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"अर्को डिभाइस प्रयोग गर्नुहोस्"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"अर्को डिभाइसमा सेभ गर्नुहोस्"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"पासकीका सहायताले सुरक्षित रहनुहोस्"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"तपाईंले पासकी बनाउनुभयो भने तपाईंले जटिल पासवर्ड बनाउनु वा तिनलाई याद गरिराख्नु पर्दैन"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"पासकी भनेको तपाईंले आफ्नो फिंगरप्रिन्ट, अनुहार वा स्क्रिन लक प्रयोग गरेर बनाएको इन्क्रिप्ट गरिएको डिजिटल की हो"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"तपाईं अन्य डिभाइसहरूमा साइन इन गर्न सक्नुहोस् भन्नाका लागि तिनलाई पासवर्ड म्यानेजरमा सेभ गरिन्छन्"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> सेभ गर्ने ठाउँ छनौट गर्नुहोस्"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"आफ्ना पासकीहरू बाउनुहोस्"</string>
- <string name="save_your_password" msgid="6597736507991704307">"आफ्नो पासवर्ड सेभ गर्नुहोस्"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"आफ्नो साइन इनसम्बन्धी जानकारी सेभ गर्नुहोस्"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"तपाईंको जानकारी सेभ गर्न कुनै पासवर्ड म्यानेजर चयन गर्नुहोस् र अर्को टपक अझ चाँडो साइन एन गर्नुहोस्।"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> को पासकी बनाउने हो?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> को पासवर्ड सेभ गर्ने हो?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> मा साइन गर्न प्रयोग गरिनु पर्ने जानकारी सेभ गर्ने हो?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"तपाईं जुनसुकै डिभाइसमा आफ्नो <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> प्रयोग गर्न सक्नुहुन्छ। यो क्रिडेन्सियल <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> का लागि <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> मा सेभ गरिएको छ।"</string>
<string name="passkey" msgid="632353688396759522">"पासकी"</string>
<string name="password" msgid="6738570945182936667">"पासवर्ड"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"अर्को डिभाइसमा पासकी बनाउने हो?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"तपाईंले साइन इन गर्ने सबै डिभाइसहरूमा <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> प्रयोग गर्ने हो?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"तपाईं सजिलै साइन इन गर्न सक्नुहोस् भन्नाका लागि यो पासवर्ड म्यानेजरले तपाईंका पासवर्ड तथा पासकीहरू सेभ गर्ने छ।"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"डिफल्ट जानकारीका रूपमा सेट गर्नुहोस्"</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>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index 4d373be..6bc731b 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Annuleren"</string>
<string name="string_continue" msgid="1346732695941131882">"Doorgaan"</string>
<string name="string_more_options" msgid="7990658711962795124">"Meer opties"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Op een andere locatie maken"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Op een andere locatie opslaan"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Een ander apparaat gebruiken"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Opslaan op een ander apparaat"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Veiliger met toegangssleutels"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Met toegangssleutels hoef je geen ingewikkelde wachtwoorden te maken of te onthouden"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Toegangssleutels zijn versleutelde digitale sleutels die je maakt met je vingerafdruk, gezicht of schermvergrendeling"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ze worden opgeslagen in een wachtwoordmanager zodat je op andere apparaten kunt inloggen"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Een locatie kiezen voor <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"je toegangssleutels maken"</string>
- <string name="save_your_password" msgid="6597736507991704307">"je wachtwoord opslaan"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"je inloggegevens opslaan"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecteer een wachtwoordmanager om je informatie op te slaan en de volgende keer sneller in te loggen."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Toegangssleutel maken voor <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Wachtwoord opslaan voor <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Inloggegevens opslaan voor <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Je kunt je <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> voor <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> op elk apparaat gebruiken. Dit wordt opgeslagen in <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> voor <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"toegangssleutel"</string>
<string name="password" msgid="6738570945182936667">"wachtwoord"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"inloggegevens"</string>
<string name="sign_in_info" msgid="2627704710674232328">"inloggegevens"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> opslaan in"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Toegangssleutel maken op een ander apparaat?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> elke keer gebruiken als je inlogt?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Deze wachtwoordmanager slaat je wachtwoorden en toegangssleutels op zodat je makkelijk kunt inloggen."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Instellen als standaard"</string>
<string name="use_once" msgid="9027366575315399714">"Eén keer gebruiken"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> wachtwoorden • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> toegangssleutels"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 7db9821..f2655c8 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="string_continue" msgid="1346732695941131882">"ଜାରି ରଖନ୍ତୁ"</string>
<string name="string_more_options" msgid="7990658711962795124">"ଅଧିକ ବିକଳ୍ପ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"ଅନ୍ୟ ଏକ ସ୍ଥାନରେ ତିଆରି କରନ୍ତୁ"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ଅନ୍ୟ ଏକ ସ୍ଥାନରେ ସେଭ କରନ୍ତୁ"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ଅନ୍ୟ ଏହି ଡିଭାଇସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ଅନ୍ୟ ଏକ ଡିଭାଇସରେ ସେଭ କରନ୍ତୁ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ପାସକୀ ସହ ଅଧିକ ସୁରକ୍ଷିତ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ପାସକୀଗୁଡ଼ିକ ସହ ଆପଣଙ୍କୁ ଜଟିଳ ପାସୱାର୍ଡଗୁଡ଼ିକ ତିଆରି କରିବା କିମ୍ବା ମନେରଖିବାର ଆବଶ୍ୟକତା ନାହିଁ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ପାସକୀଗୁଡ଼ିକ ହେଉଛି ଆପଣ ଆପଣଙ୍କ ଟିପଚିହ୍ନ, ଫେସ କିମ୍ବା ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରି ତିଆରି କରୁଥିବା ଏକକ୍ରିପ୍ଟ କରାଯାଇଥିବା ଡିଜିଟାଲ କୀ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ସେଗୁଡ଼ିକୁ ଏକ Password Managerରେ ସେଭ କରାଯାଏ, ଯାହା ଫଳରେ ଆପଣ ଅନ୍ୟ ଡିଭାଇସଗୁଡ଼ିକରେ ସାଇନ ଇନ କରିପାରିବେ"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"କେଉଁଠି <xliff:g id="CREATETYPES">%1$s</xliff:g> କରିବେ, ତାହା ବାଛନ୍ତୁ"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ଆପଣଙ୍କ ପାସକୀଗୁଡ଼ିକ ତିଆରି କରନ୍ତୁ"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ଆପଣଙ୍କ ପାସୱାର୍ଡ ସେଭ କରନ୍ତୁ"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ଆପଣଙ୍କ ସାଇନ-ଇନ ସୂଚନା ସେଭ କରନ୍ତୁ"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ଆପଣଙ୍କ ସୂଚନା ସେଭ କରି ପରବର୍ତ୍ତୀ ସମୟରେ ଶୀଘ୍ର ସାଇନ ଇନ କରିବା ପାଇଁ ଏକ Password Manager ଚୟନ କରନ୍ତୁ।"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ପାସକୀ ତିଆରି କରିବେ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ପାସୱାର୍ଡ ସେଭ କରିବେ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> ପାଇଁ ସାଇନ-ଇନର ସୂଚନା ସେଭ କରିବେ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"ଆପଣ ଯେ କୌଣସି ଡିଭାଇସରେ ଆପଣଙ୍କ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>କୁ ବ୍ୟବହାର କରିପାରିବେ। ଏହାକୁ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> ପାଇଁ <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>ରେ ସେଭ କରାଯାଏ।"</string>
<string name="passkey" msgid="632353688396759522">"ପାସକୀ"</string>
<string name="password" msgid="6738570945182936667">"ପାସୱାର୍ଡ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"ଅନ୍ୟ ଏକ ଡିଭାଇସରେ ପାସକୀ ତିଆରି କରିବେ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ଆପଣଙ୍କ ସମସ୍ତ ସାଇନ-ଇନ ପାଇଁ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ବ୍ୟବହାର କରିବେ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ଏହି Password Manager ସହଜରେ ସାଇନ ଇନ କରିବାରେ ଆପଣଙ୍କୁ ସାହାଯ୍ୟ କରିବା ପାଇଁ ଆପଣଙ୍କ ପାସୱାର୍ଡ ଏବଂ ପାସକୀଗୁଡ଼ିକୁ ଷ୍ଟୋର କରିବ।"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ଡିଫଲ୍ଟ ଭାବେ ସେଟ କରନ୍ତୁ"</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>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index b9d72f8..824b5db 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ਰੱਦ ਕਰੋ"</string>
<string name="string_continue" msgid="1346732695941131882">"ਜਾਰੀ ਰੱਖੋ"</string>
<string name="string_more_options" msgid="7990658711962795124">"ਹੋਰ ਵਿਕਲਪ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"ਕਿਸੇ ਹੋਰ ਥਾਂ \'ਤੇ ਬਣਾਓ"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"ਕਿਸੇ ਹੋਰ ਥਾਂ \'ਤੇ ਰੱਖਿਅਤ ਕਰੋ"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ਕੋਈ ਹੋਰ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ \'ਤੇ ਰੱਖਿਅਤ ਕਰੋ"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ਪਾਸਕੀਆਂ ਨਾਲ ਸੁਰੱਖਿਅਤ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"ਪਾਸਕੀਆਂ ਨਾਲ, ਤੁਹਾਨੂੰ ਜਟਿਲ ਪਾਸਵਰਡ ਬਣਾਉਣ ਜਾਂ ਯਾਦ ਰੱਖਣ ਦੀ ਲੋੜ ਨਹੀਂ ਹੁੰਦੀ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"ਪਾਸਕੀਆਂ ਇਨਕ੍ਰਿਪਟਡ ਡਿਜੀਟਲ ਕੁੰਜੀਆਂ ਹੁੰਦੀਆਂ ਹਨ ਜੋ ਤੁਹਾਡੇ ਵੱਲੋਂ ਤੁਹਾਡੇ ਫਿੰਗਰਪ੍ਰਿੰਟ, ਚਿਹਰੇ ਜਾਂ ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਬਣਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ਉਨ੍ਹਾਂ ਨੂੰ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ \'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਜੋ ਤੁਸੀਂ ਹੋਰ ਡੀਵਾਈਸਾਂ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰ ਸਕੋ"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> ਲਈ ਕੋਈ ਥਾਂ ਚੁਣੋ"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ਆਪਣੀਆਂ ਪਾਸਕੀਆਂ ਬਣਾਓ"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ਆਪਣਾ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰੋ"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ਆਪਣੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਰੱਖਿਅਤ ਕਰੋ"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ਆਪਣੀ ਜਾਣਕਾਰੀ ਨੂੰ ਰੱਖਿਅਤ ਕਰਨ ਅਤੇ ਅਗਲੀ ਵਾਰ ਤੇਜ਼ੀ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ ਚੁਣੋ।"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਲਈ ਪਾਸਕੀ ਬਣਾਉਣੀ ਹੈ?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਲਈ ਪਾਸਵਰਡ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"ਕੀ <xliff:g id="APPNAME">%1$s</xliff:g> ਲਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਰੱਖਿਅਤ ਕਰਨੀ ਹੈ?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"ਤੁਸੀਂ ਕਿਸੇ ਵੀ ਡੀਵਾਈਸ \'ਤੇ ਆਪਣੀ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ। ਇਸਨੂੰ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> ਲਈ <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ।"</string>
<string name="passkey" msgid="632353688396759522">"ਪਾਸਕੀ"</string>
<string name="password" msgid="6738570945182936667">"ਪਾਸਵਰਡ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"ਕੀ ਕਿਸੇ ਹੋਰ ਡੀਵਾਈਸ ਵਿੱਚ ਕੋਈ ਪਾਸਕੀ ਬਣਾਉਣੀ ਹੈ?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ਕੀ ਆਪਣੇ ਸਾਰੇ ਸਾਈਨ-ਇਨਾਂ ਲਈ<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"ਇਹ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਆਸਾਨੀ ਨਾਲ ਸਾਈਨ-ਇਨ ਕਰਨ ਵਿੱਚ ਮਦਦ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਾਸਕੀਆਂ ਨੂੰ ਸਟੋਰ ਕਰੇਗਾ।"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਜੋਂ ਸੈੱਟ ਕਰੋ"</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>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index 503e8e8..8ba182d 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Anuluj"</string>
<string name="string_continue" msgid="1346732695941131882">"Dalej"</string>
<string name="string_more_options" msgid="7990658711962795124">"Więcej opcji"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Utwórz w innym miejscu"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Zapisz w innym miejscu"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Użyj innego urządzenia"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Zapisz na innym urządzeniu"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Klucze zwiększają Twoje bezpieczeństwo"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dzięki kluczom nie musisz tworzyć ani zapamiętywać skomplikowanych haseł"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Klucze są szyfrowanymi kluczami cyfrowymi, które tworzysz za pomocą funkcji rozpoznawania odcisku palca lub twarzy bądź blokady ekranu"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Klucze są zapisane w menedżerze haseł, dzięki czemu możesz logować się na innych urządzeniach"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Wybierz, gdzie chcesz <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"tworzyć klucze"</string>
- <string name="save_your_password" msgid="6597736507991704307">"zapisać hasło"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"zapisać dane logowania"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Wybierz menedżera haseł, aby zapisywać informacje i logować się szybciej."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Utworzyć klucz dla aplikacji <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Zapisać hasło do aplikacji <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Zapisać dane logowania do aplikacji <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Elementu typu <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> dla aplikacji <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> możesz używać na każdym urządzeniu. Jest zapisany w usłudze <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> (<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>)."</string>
<string name="passkey" msgid="632353688396759522">"klucz"</string>
<string name="password" msgid="6738570945182936667">"hasło"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"dane logowania"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informacje dotyczące logowania"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Zapisać: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> w:"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Utworzyć klucz na innym urządzeniu?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Używać usługi <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> w przypadku wszystkich danych logowania?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Menedżer haseł będzie zapisywał Twoje hasła i klucze, aby ułatwić Ci logowanie."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Ustaw jako domyślną"</string>
<string name="use_once" msgid="9027366575315399714">"Użyj raz"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Hasła: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Klucze: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 0ee1ef6..7aac738 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Criar em outro lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Salvar em outro lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar outro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Salvar em outro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elas são salvas em um gerenciador de senhas para que você possa fazer login em outros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Escolha onde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crie suas chaves de acesso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"salvar sua senha"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"salvar suas informações de login"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecione um gerenciador de senhas para salvar suas informações e fazer login rapidamente na próxima vez."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde salvar suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gerenciador de senhas para salvar suas informações e fazer login mais rapidamente na próxima vez"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para o app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Salvar senha do app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Salvar informações de login do app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Você pode usar a <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> do app <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> em qualquer dispositivo. Ela fica salva no <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> de <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"chave de acesso"</string>
<string name="password" msgid="6738570945182936667">"senha"</string>
+ <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string>
+ <string name="passwords" msgid="5419394230391253816">"senhas"</string>
<string name="sign_ins" msgid="4710739369149469208">"logins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informações de login"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Salvar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Criar uma chave de acesso em outro dispositivo?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso em outro dispositivo?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus logins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Esse gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login"</string>
<string name="set_as_default" msgid="4415328591568654603">"Definir como padrão"</string>
<string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> senhas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 7376ab2..df8477e 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Criar noutro lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Guardar noutro lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar outro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Guardar noutro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com chaves de acesso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, não precisa de criar nem memorizar palavras-passe complexas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais encriptadas que cria através da sua impressão digital, rosto ou bloqueio de ecrã"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"São guardadas num gestor de palavras-passe para que possa iniciar sessão noutros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Escolha onde quer guardar <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"criar as suas chaves de acesso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"guardar a sua palavra-passe"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"guardar as suas informações de início de sessão"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecione um gestor de palavras-passe para guardar as suas informações e iniciar sessão mais rapidamente da próxima vez."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde guardar as suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gestor de palavras-passe para guardar as suas informações e iniciar sessão mais rapidamente da próxima vez"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para a app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Guardar a palavra-passe da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Guardar as informações de início de sessão da app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Pode usar <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> de <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> em qualquer dispositivo. É guardada no <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> de <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"chave de acesso"</string>
<string name="password" msgid="6738570945182936667">"palavra-passe"</string>
+ <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string>
+ <string name="passwords" msgid="5419394230391253816">"palavras-passe"</string>
<string name="sign_ins" msgid="4710739369149469208">"inícios de sessão"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informações de início de sessão"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Guarde <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Criar uma chave de acesso noutro dispositivo?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso noutro dispositivo?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus inícios de sessão?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este gestor de palavras-passe armazena as suas palavras-passe e chaves de acesso para ajudar a iniciar sessão facilmente."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Este gestor de palavras-passe armazena as suas palavras-passe e chaves de acesso para ajudar a iniciar sessão facilmente"</string>
<string name="set_as_default" msgid="4415328591568654603">"Definir como predefinição"</string>
<string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> palavras-passe • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 0ee1ef6..7aac738 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
<string name="string_more_options" msgid="7990658711962795124">"Mais opções"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Criar em outro lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Salvar em outro lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Usar outro dispositivo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Salvar em outro dispositivo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mais segurança com as chaves de acesso"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Com as chaves de acesso, você não precisa criar nem se lembrar de senhas complexas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"As chaves de acesso são chaves digitais criptografadas que você cria usando a impressão digital, o rosto ou o bloqueio de tela"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Elas são salvas em um gerenciador de senhas para que você possa fazer login em outros dispositivos"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Escolha onde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"crie suas chaves de acesso"</string>
- <string name="save_your_password" msgid="6597736507991704307">"salvar sua senha"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"salvar suas informações de login"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selecione um gerenciador de senhas para salvar suas informações e fazer login rapidamente na próxima vez."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Escolha onde salvar suas <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Selecione um gerenciador de senhas para salvar suas informações e fazer login mais rapidamente na próxima vez"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Criar uma chave de acesso para o app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Salvar senha do app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Salvar informações de login do app <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Você pode usar a <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> do app <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> em qualquer dispositivo. Ela fica salva no <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> de <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"chave de acesso"</string>
<string name="password" msgid="6738570945182936667">"senha"</string>
+ <string name="passkeys" msgid="5733880786866559847">"chaves de acesso"</string>
+ <string name="passwords" msgid="5419394230391253816">"senhas"</string>
<string name="sign_ins" msgid="4710739369149469208">"logins"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informações de login"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Salvar <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> em"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Criar uma chave de acesso em outro dispositivo?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Criar chave de acesso em outro dispositivo?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Usar <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para todos os seus logins?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Este gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Esse gerenciador de senhas vai armazenar suas senhas e chaves de acesso para facilitar o processo de login"</string>
<string name="set_as_default" msgid="4415328591568654603">"Definir como padrão"</string>
<string name="use_once" msgid="9027366575315399714">"Usar uma vez"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> senhas • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chaves de acesso"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index 0ccd242..10ff472 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Anulează"</string>
<string name="string_continue" msgid="1346732695941131882">"Continuă"</string>
<string name="string_more_options" msgid="7990658711962795124">"Mai multe opțiuni"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Creează în alt loc"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Salvează în alt loc"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Folosește alt dispozitiv"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Salvează pe alt dispozitiv"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mai în siguranță cu chei de acces"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Dacă folosești chei de acces, nu este nevoie să creezi sau să reții parole complexe"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Cheile de acces sunt chei digitale criptate pe care le creezi folosindu-ți amprenta, fața sau blocarea ecranului"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Acestea sunt salvate într-un manager de parole, ca să te poți conecta pe alte dispozitive"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Alege unde <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"creează cheile de acces"</string>
- <string name="save_your_password" msgid="6597736507991704307">"salvează parola"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"salvează informațiile de conectare"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Selectează un manager de parole pentru a salva informațiile și a te conecta mai rapid data viitoare."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Creezi o cheie de acces pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Salvezi parola pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Salvezi informațiile de conectare pentru <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Poți folosi <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> pe orice dispozitiv. Se salvează în <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> pentru <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"cheie de acces"</string>
<string name="password" msgid="6738570945182936667">"parolă"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"date de conectare"</string>
<string name="sign_in_info" msgid="2627704710674232328">"informațiile de conectare"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Salvează <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> în"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Creezi o cheie de acces în alt dispozitiv?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Folosești <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> pentru toate conectările?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Managerul de parole îți va stoca parolele și cheile de acces, pentru a te ajuta să te conectezi cu ușurință."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Setează ca prestabilite"</string>
<string name="use_once" msgid="9027366575315399714">"Folosește o dată"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> parole • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> chei de acces"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index 4528563..9a0d979 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Отмена"</string>
<string name="string_continue" msgid="1346732695941131882">"Продолжить"</string>
<string name="string_more_options" msgid="7990658711962795124">"Ещё"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Создать в другом месте"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Сохранить в другом месте"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Использовать другое устройство"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Сохранить на другом устройстве"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ключи доступа безопаснее"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Благодаря ключам доступа вам не придется создавать или запоминать сложные пароли."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключ доступа – это зашифрованное цифровое удостоверение, которое создается с использованием отпечатка пальца, функции фейсконтроля или блокировки экрана."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Данные хранятся в менеджере паролей, чтобы вы могли входить в аккаунт на других устройствах."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Выберите, где <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"создать ключи доступа"</string>
- <string name="save_your_password" msgid="6597736507991704307">"сохранить пароль"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"сохранить данные для входа"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Выберите менеджер паролей, чтобы сохранять учетные данные и быстро выполнять вход."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Создать ключ доступа для приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Сохранить пароль для приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Сохранить учетные данные для приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Вы можете использовать <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> для приложения \"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>\" на любом устройстве. Данные <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> сохраняются в приложении \"<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>\"."</string>
<string name="passkey" msgid="632353688396759522">"ключ доступа"</string>
<string name="password" msgid="6738570945182936667">"пароль"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Создать ключ доступа на другом устройстве?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Всегда входить с помощью приложения \"<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>\"?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"В этом менеджере паролей можно сохранять учетные данные, например ключи доступа, чтобы потом использовать их."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Использовать по умолчанию"</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>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index e5084d8f..11a7a38 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"අවලංගු කරන්න"</string>
<string name="string_continue" msgid="1346732695941131882">"ඉදිරියට යන්න"</string>
<string name="string_more_options" msgid="7990658711962795124">"තවත් විකල්ප"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"වෙනත් ස්ථානයක තනන්න"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"වෙනත් ස්ථානයකට සුරකින්න"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"වෙනත් උපාංගයක් භාවිතා කරන්න"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"වෙනත් උපාංගයකට සුරකින්න"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"මුරයතුරු සමග සුරක්ෂිතයි"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"මුරයතුරු සමග, ඔබට සංකීර්ණ මුරපද තැනීමට හෝ මතක තබා ගැනීමට අවශ්ය නොවේ"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"මුරයතුරු යනු ඔබේ ඇඟිලි සලකුණ, මුහුණ, හෝ තිර අගුල භාවිතයෙන් ඔබ තනන සංකේතාත්මක ඩිජිටල් යතුරු වේ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ඒවා මුරපද කළමනාකරුවෙකු වෙත සුරකින බැවින්, ඔබට වෙනත් උපාංග මත පුරනය විය හැක"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> කොතැනක ද යන්න තෝරා ගන්න"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ඔබේ මුරයතුරු තනන්න"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ඔබේ මුරපදය සුරකින්න"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ඔබේ පුරනය වීමේ තතු සුරකින්න"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"ඔබේ තතු සුරැකීමට සහ මීළඟ වතාවේ වේගයෙන් පුරනය වීමට මුරපද කළමනාකරුවෙකු තෝරන්න."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> සඳහා මුරයතුර තනන්න ද?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> සඳහා මුරපදය සුරකින්න ද?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> සඳහා පුරනය වීමේ තතු සුරකින්න ද?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"ඔබට ඕනෑම උපාංගයක ඔබේ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> භාවිතා කළ හැක. එය <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> සඳහා <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> වෙත සුරැකෙයි."</string>
<string name="passkey" msgid="632353688396759522">"මුරයතුර"</string>
<string name="password" msgid="6738570945182936667">"මුරපදය"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"වෙනත් උපාංගයක මුරයතුරක් තනන්න ද?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ඔබේ සියලු පුරනය වීම් සඳහා <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> භාවිතා කරන්න ද?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"මෙම මුරපද කළමනාකරු ඔබට පහසුවෙන් පුරනය වීමට උදවු කිරීම සඳහා ඔබේ මුරපද සහ මුරයතුරු ගබඩා කරනු ඇත."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"පෙරනිමි ලෙස සකසන්න"</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>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 7da7d63..eba5779 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Zrušiť"</string>
<string name="string_continue" msgid="1346732695941131882">"Pokračovať"</string>
<string name="string_more_options" msgid="7990658711962795124">"Ďalšie možnosti"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Vytvoriť inde"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Uložiť inde"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Použiť iné zariadenie"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Uložiť do iného zariadenia"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Bezpečnejšie s prístupovými kľúčmi"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Ak máte prístupové kľúče, nemusíte vytvárať ani si pamätať zložité heslá"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Prístupové kľúče sú šifrované digitálne kľúče, ktoré môžete vytvoriť odtlačkom prsta, tvárou alebo zámkou obrazovky."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ukladajú sa do správcu hesiel, aby ste sa mohli prihlasovať v iných zariadeniach"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Vyberte, kam <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"vytvoriť prístupové kľúče"</string>
- <string name="save_your_password" msgid="6597736507991704307">"uložiť heslo"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"uložiť prihlasovacie údaje"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Vyberte si správcu hesiel, do ktorého sa budú ukladať vaše údaje, aby ste sa nabudúce rýchlejšie prihlásili."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Chcete vytvoriť prístupový kľúč pre aplikáciu <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Chcete uložiť heslo pre aplikáciu <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Chcete uložiť prihlasovacie údaje pre aplikáciu <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Pripomíname, že <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> aplikácie <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> môžete používať v ľubovoľnom zariadení. Uchováva sa v službe <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> pre účet <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"prístupový kľúč"</string>
<string name="password" msgid="6738570945182936667">"heslo"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"prihlasovacie údaje"</string>
<string name="sign_in_info" msgid="2627704710674232328">"prihlasovacie údaje"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Uložiť <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> do"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Chcete vytvoriť prístupový kľúč v inom zariadení?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Chcete pre všetky svoje prihlasovacie údaje použiť <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Tento správca hesiel uchová vaše heslá a prístupové kľúče, aby vám pomohol ľahšie sa prihlasovať."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Nastaviť ako predvolené"</string>
<string name="use_once" msgid="9027366575315399714">"Použiť raz"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Počet hesiel: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Počet prístupových kľúčov: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index af3504a..7201f32 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Prekliči"</string>
<string name="string_continue" msgid="1346732695941131882">"Naprej"</string>
<string name="string_more_options" msgid="7990658711962795124">"Več možnosti"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Ustvarjanje na drugem mestu"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Shranjevanje na drugo mesto"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Uporabi drugo napravo"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Shrani v drugo napravo"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Večja varnost s ključi za dostop"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Po zaslugi ključev za dostop vam ni treba ustvarjati ali si zapomniti zapletenih gesel."</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ključi za dostop so šifrirani digitalni ključi, ki jih ustvarite s prstnim odtisom, obrazom ali načinom zaklepanja zaslona."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Shranjeni so v upravitelju gesel, kar pomeni, da se z njimi lahko prijavite tudi v drugih napravah."</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Izberite mesto za <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"ustvarjanje ključev za dostop"</string>
- <string name="save_your_password" msgid="6597736507991704307">"shranjevanje gesla"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"shranjevanje podatkov za prijavo"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Izberite upravitelja gesel za shranjevanje podatkov za prijavo, da se boste naslednjič lahko hitreje prijavili."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Želite ustvariti ključ za dostop do aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Želite shraniti geslo za aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Želite shraniti podatke za prijavo za aplikacijo <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> za <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> lahko uporabite v kateri koli napravi. Shranjeno je pod »<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>« za »<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>«."</string>
<string name="passkey" msgid="632353688396759522">"ključ za dostop"</string>
<string name="password" msgid="6738570945182936667">"geslo"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"prijave"</string>
<string name="sign_in_info" msgid="2627704710674232328">"podatkov za prijavo"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Mesto shranjevanja <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Želite ustvariti ključ za dostop v drugi napravi?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Želite za vse prijave uporabiti »<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>«?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"V tem upravitelju gesel bodo shranjeni gesla in ključi za dostop, kar vam bo olajšalo prijavo."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Nastavi kot privzeto"</string>
<string name="use_once" msgid="9027366575315399714">"Uporabi enkrat"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Št. gesel: <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • Št. ključev za dostop: <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 38a2c22..87cc2fe 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Anulo"</string>
<string name="string_continue" msgid="1346732695941131882">"Vazhdo"</string>
<string name="string_more_options" msgid="7990658711962795124">"Opsione të tjera"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Krijo në një vend tjetër"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Ruaj në një vend tjetër"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Përdor një pajisje tjetër"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Ruaj në një pajisje tjetër"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Më e sigurt me çelësat e kalimit"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Me çelësat e kalimit, nuk ka nevojë të krijosh ose të mbash mend fjalëkalime të ndërlikuara"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Çelësat e kalimit kanë çelësa dixhitalë të enkriptuar që ti i krijon duke përdorur gjurmën e gishtit, fytyrën ose kyçjen e ekranit"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ata ruhen te një menaxher fjalëkalimesh, në mënyrë që mund të identifikohesh në pajisje të tjera"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Zgjidh se ku të <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"do t\'i krijosh çelësat e tu të kalimit"</string>
- <string name="save_your_password" msgid="6597736507991704307">"ruaj fjalëkalimin"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"ruaj informacionet e tua të identifikimit"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Zgjidh një menaxher fjalëkalimesh për të ruajtur informacionet e tua dhe për t\'u identifikuar më shpejt herën tjetër."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Të krijohet çelësi i kalimit për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Të ruhet fjalëkalimi për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Të ruhen informacionet e identifikimit për <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Mund të përdorësh <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> të <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> në çdo pajisje. Ai është i ruajtur te \"<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>\" për <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"çelësi i kalimit"</string>
<string name="password" msgid="6738570945182936667">"fjalëkalimi"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="create_passkey_in_other_device_title" msgid="6372952459932674632">"Të krijohet një çelës kalimi në një pajisje tjetër?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Të përdoret <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> për të gjitha identifikimet?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Ky menaxher i fjalëkalimeve do të ruajë fjalëkalimet dhe çelësat e kalimit për të të ndihmuar të identifikohesh me lehtësi."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Cakto si parazgjedhje"</string>
<string name="use_once" msgid="9027366575315399714">"Përdor një herë"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> fjalëkalime • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> çelësa kalimi"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index a83c629..80c0537 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Откажи"</string>
<string name="string_continue" msgid="1346732695941131882">"Настави"</string>
<string name="string_more_options" msgid="7990658711962795124">"Још опција"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Направи на другом месту"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Сачувај на другом месту"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Користи други уређај"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Сачувај на други уређај"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Безбедније уз приступне кодове"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Уз приступне кодове нема потребе да правите или памтите сложене лозинке"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Приступни кодови су шифровани дигитални кодови које правите помоћу отиска прста, лица или закључавања екрана"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Чувају се у менаџеру лозинки да бисте могли да се пријављујете на другим уређајима"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Одаберите локацију за: <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"направите приступне кодове"</string>
- <string name="save_your_password" msgid="6597736507991704307">"сачувајте лозинку"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"сачувајте податке о пријављивању"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Изаберите менаџера лозинки да бисте сачували податке и брже се пријавили следећи пут."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Желите да направите приступни кôд за: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Желите да сачувате лозинку за: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Желите да сачувате податке за пријављивање за: <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Можете да користите тип домена <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> на било ком уређају. Чува се код корисника <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> за: <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"приступни кôд"</string>
<string name="password" msgid="6738570945182936667">"лозинка"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Желите да направите приступни кôд на другом уређају?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Желите да за сва пријављивања користите: <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Овај менаџер лозинки ће чувати лозинке и приступне кодове да бисте се лако пријављивали."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Подеси као подразумевано"</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>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index 502f03e..ab8c5aa 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Avbryt"</string>
<string name="string_continue" msgid="1346732695941131882">"Fortsätt"</string>
<string name="string_more_options" msgid="7990658711962795124">"Fler alternativ"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Skapa på en annan plats"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Spara på en annan plats"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Använd en annan enhet"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Spara på en annan enhet"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Säkrare med nycklar"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Med nycklar behöver du inte skapa eller komma ihop invecklade lösenord"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Nycklar är krypterade digitala nycklar som du skapar med ditt fingeravtryck, ansikte eller skärmlås"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"De sparas i lösenordshanteraren så att du kan logga in på andra enheter"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Välj var du <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"skapa nycklar"</string>
- <string name="save_your_password" msgid="6597736507991704307">"spara lösenordet"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"spara inloggningsuppgifterna"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Välj en lösenordshanterare för att spara dina uppgifter och logga in snabbare nästa gång."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Välj var du vill spara <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Välj en lösenordshanterare för att spara dina uppgifter och logga in snabbare nästa gång"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Vill du skapa en nyckel för <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Vill du spara lösenordet för <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Vill du spara inloggningsuppgifterna för <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Du kan använda <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> för <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> på alla enheter. Du kan spara uppgifterna i <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> för <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"nyckel"</string>
<string name="password" msgid="6738570945182936667">"lösenord"</string>
+ <string name="passkeys" msgid="5733880786866559847">"nycklar"</string>
+ <string name="passwords" msgid="5419394230391253816">"lösenord"</string>
<string name="sign_ins" msgid="4710739369149469208">"inloggningar"</string>
<string name="sign_in_info" msgid="2627704710674232328">"inloggningsuppgifter"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Spara <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> i"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Vill du skapa en nyckel på en annan enhet?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Vill du skapa en nyckel på en annan enhet?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Vill du använda <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> för alla dina inloggningar?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Den här lösenordshanteraren sparar dina lösenord och nycklar för att underlätta inloggning."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Den här lösenordshanteraren sparar dina lösenord och nycklar för att underlätta inloggning"</string>
<string name="set_as_default" msgid="4415328591568654603">"Ange som standard"</string>
<string name="use_once" msgid="9027366575315399714">"Använd en gång"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> lösenord • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> nycklar"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 0cba399..1685882 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Ghairi"</string>
<string name="string_continue" msgid="1346732695941131882">"Endelea"</string>
<string name="string_more_options" msgid="7990658711962795124">"Chaguo zaidi"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Unda katika sehemu nyingine"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Hifadhi sehemu nyingine"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Tumia kifaa kingine"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Hifadhi kwenye kifaa kingine"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ni salama ukitumia funguo za siri"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kwa kutumia funguo za siri, huhitaji kuunda au kukumbuka manenosiri changamano"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Funguo za siri ni funguo dijitali zilizosimbwa kwa njia fiche unazounda kwa kutumia alama yako ya kidole, uso au mbinu ya kufunga skrini"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Vyote huhifadhiwa kwenye kidhibiti cha manenosiri, ili uweze kuingia katika akaunti kwenye vifaa vingine"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Chagua mahali pa <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"unda funguo zako za siri"</string>
- <string name="save_your_password" msgid="6597736507991704307">"hifadhi nenosiri lako"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"hifadhi maelezo yako ya kuingia katika akaunti"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Chagua kidhibiti cha manenosiri ili uhifadhi taarifa zako na uingie kwenye akaunti kwa urahisi wakati mwingine."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Ungependa kuunda ufunguo wa siri kwa ajili ya <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Ungependa kuhifadhi nenosiri kwa ajili ya <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Ungependa kuhifadhi maelezo ya kuingia katika akaunti kwa ajili ya <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Unaweza kutumia <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> wa <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> kwenye kifaa chochote. Umehifadhiwa kwenye <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> kwa ajili ya <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"ufunguo wa siri"</string>
<string name="password" msgid="6738570945182936667">"nenosiri"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"michakato ya kuingia katika akaunti"</string>
<string name="sign_in_info" msgid="2627704710674232328">"maelezo ya kuingia katika akaunti"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Hifadhi <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> kwenye"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Ungependa kuunda ufunguo wa siri kwenye kifaa kingine?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Ungependa kutumia <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kwa ajili ya michakato yako yote ya kuingia katika akaunti?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Kidhibiti hiki cha manenosiri kitahifadhi manenosiri na funguo zako za siri ili kukusaidia uingie katika akaunti kwa urahisi."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Weka iwe chaguomsingi"</string>
<string name="use_once" msgid="9027366575315399714">"Tumia mara moja"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Manenosiri <xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • funguo <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> za siri"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 7650803..5c68f66 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"ரத்துசெய்"</string>
<string name="string_continue" msgid="1346732695941131882">"தொடர்க"</string>
<string name="string_more_options" msgid="7990658711962795124">"கூடுதல் விருப்பங்கள்"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"மற்றொரு இடத்தில் உருவாக்கவும்"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"மற்றொரு இடத்தில் சேமிக்கவும்"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"மற்றொரு சாதனத்தைப் பயன்படுத்தவும்"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"வேறொரு சாதனத்தில் சேமியுங்கள்"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"கடவுச்சாவிகள் மூலம் பாதுகாப்பாக வைத்திருங்கள்"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"கடவுச்சாவிகளைப் பயன்படுத்துவதன் மூலம் கடினமான கடவுச்சொற்களை உருவாக்கவோ நினைவில்கொள்ளவோ தேவையில்லை"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"கடவுச்சாவிகள் என்பவை உங்கள் கைரேகை, முகம் அல்லது திரைப் பூட்டு மூலம் உருவாக்கப்படும் என்க்ரிப்ஷன் செய்யப்பட்ட டிஜிட்டல் சாவிகள் ஆகும்"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"அவை Password Managerரில் சேமிக்கப்பட்டுள்ளதால் நீங்கள் பிற சாதனங்களிலிருந்து உள்நுழையலாம்"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> எங்கே காட்டப்பட வேண்டும் என்பதைத் தேர்வுசெய்தல்"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"உங்கள் கடவுச்சாவிகளை உருவாக்குங்கள்"</string>
- <string name="save_your_password" msgid="6597736507991704307">"உங்கள் கடவுச்சொல்லைச் சேமிக்கவும்"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"உங்கள் உள்நுழைவு தகவலைச் சேமிக்கவும்"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"உங்கள் விவரங்களைச் சேமிக்கவும் அடுத்த முறை வேகமாக உள்நுழையவும் Password Managerரைத் தேர்ந்தெடுக்கவும்."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான கடவுச்சாவியை உருவாக்கவா?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான கடவுச்சொல்லைச் சேமிக்கவா?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> ஆப்ஸுக்கான உள்நுழைவு விவரங்களைச் சேமிக்கவா?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"உங்கள் <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ஐ எந்தச் சாதனத்தில் வேண்டுமானாலும் பயன்படுத்தலாம். <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>ரில் <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> என்ற மின்னஞ்சல் முகவரிக்குச் சேமிக்கப்பட்டுள்ளது."</string>
<string name="passkey" msgid="632353688396759522">"கடவுக்குறியீடு"</string>
<string name="password" msgid="6738570945182936667">"கடவுச்சொல்"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"வேறொரு சாதனத்தில் கடவுச்சாவியை உருவாக்கவா?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"உங்கள் அனைத்து உள்நுழைவுகளுக்கும் <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ஐப் பயன்படுத்தவா?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"எளிதில் உள்நுழைவதற்கு உதவும் வகையில் இந்த Password Manager உங்கள் கடவுச்சொற்களையும் கடவுச்சாவிகளையும் சேமிக்கும்."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"இயல்பானதாக அமை"</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>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 7581bbc..f428ced 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"రద్దు చేయండి"</string>
<string name="string_continue" msgid="1346732695941131882">"కొనసాగించండి"</string>
<string name="string_more_options" msgid="7990658711962795124">"మరిన్ని ఆప్షన్లు"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"మరొక స్థలంలో క్రియేట్ చేయండి"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"మరొక స్థలంలో సేవ్ చేయండి"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"మరొక పరికరాన్ని ఉపయోగించండి"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"మరొక పరికరంలో సేవ్ చేయండి"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"పాస్-కీలతో సురక్షితంగా చెల్లించవచ్చు"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"పాస్-కీలతో, మీరు క్లిష్టమైన పాస్వర్డ్లను క్రియేట్ చేయనవసరం లేదు లేదా గుర్తుంచుకోనవసరం లేదు"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"పాస్-కీలు అనేవి మీ వేలిముద్రను, ముఖాన్ని లేదా స్క్రీన్ లాక్ను ఉపయోగించి మీరు క్రియేట్ చేసే ఎన్క్రిప్ట్ చేసిన డిజిటల్ కీలు"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"అవి Password Managerకు సేవ్ చేయబడతాయి, తద్వారా మీరు ఇతర పరికరాలలో సైన్ ఇన్ చేయవచ్చు"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"ఎక్కడ <xliff:g id="CREATETYPES">%1$s</xliff:g> చేయాలో ఎంచుకోండి"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"మీ పాస్-కీలను క్రియేట్ చేయండి"</string>
- <string name="save_your_password" msgid="6597736507991704307">"మీ పాస్వర్డ్ను సేవ్ చేయండి"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"మీ సైన్ ఇన్ సమాచారాన్ని సేవ్ చేయండి"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"మీ సమాచారాన్ని సేవ్ చేయడం కోసం ఒక Password Managerను ఎంచుకొని, తర్వాతసారి వేగంగా సైన్ ఇన్ చేయండి."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"మీ <xliff:g id="CREATETYPES">%1$s</xliff:g>ని ఎక్కడ సేవ్ చేయాలో ఎంచుకోండి"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"మీ సమాచారాన్ని సేవ్ చేయడం కోసం ఒక Password Managerను ఎంచుకొని, తర్వాతసారి వేగంగా సైన్ ఇన్ చేయండి"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం పాస్కీని క్రియేట్ చేయాలా?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం పాస్వర్డ్ను సేవ్ చేయాలా?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> కోసం సైన్ ఇన్ సమాచారాన్ని సేవ్ చేయాలా?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"మీరు మీ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>ను ఏ పరికరంలోనైనా ఉపయోగించవచ్చు. ఇది <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> కోసం <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>లో సేవ్ చేయబడింది."</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="6372952459932674632">"మరొక పరికరంలో పాస్-కీని క్రియేట్ చేయాలా?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"మరొక పరికరంలో పాస్కీని క్రియేట్ చేయాలా?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"మీ అన్ని సైన్-ఇన్ వివరాల కోసం <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>ను ఉపయోగించాలా?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"మీరు సులభంగా సైన్ ఇన్ చేయడంలో సహాయపడటానికి ఈ పాస్వర్డ్ మేనేజర్ మీ పాస్వర్డ్లు, పాస్-కీలను స్టోర్ చేస్తుంది."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"మీరు సులభంగా సైన్ ఇన్ చేయడంలో సహాయపడటానికి ఈ పాస్వర్డ్ మేనేజర్ మీ పాస్వర్డ్లు, పాస్-కీలను స్టోర్ చేస్తుంది"</string>
<string name="set_as_default" msgid="4415328591568654603">"ఆటోమేటిక్ సెట్టింగ్గా సెట్ చేయండి"</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>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 8dc3357..5362d48 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"ยกเลิก"</string>
<string name="string_continue" msgid="1346732695941131882">"ต่อไป"</string>
<string name="string_more_options" msgid="7990658711962795124">"ตัวเลือกเพิ่มเติม"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"สร้างในตำแหน่งอื่น"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"บันทึกลงในตำแหน่งอื่น"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"ใช้อุปกรณ์อื่น"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"ย้ายไปยังอุปกรณ์อื่น"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"ปลอดภัยขึ้นด้วยพาสคีย์"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"พาสคีย์ช่วยให้คุณไม่ต้องสร้างหรือจำรหัสผ่านที่ซับซ้อน"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"พาสคีย์คือกุญแจดิจิทัลที่เข้ารหัสซึ่งคุณสร้างโดยใช้ลายนิ้วมือ ใบหน้า หรือการล็อกหน้าจอ"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ข้อมูลนี้จะบันทึกอยู่ในเครื่องมือจัดการรหัสผ่านเพื่อให้คุณลงชื่อเข้าใช้ในอุปกรณ์อื่นๆ ได้"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"เลือกตำแหน่งที่จะ <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"สร้างพาสคีย์"</string>
- <string name="save_your_password" msgid="6597736507991704307">"บันทึกรหัสผ่าน"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"บันทึกข้อมูลการลงชื่อเข้าใช้"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"เลือกเครื่องมือจัดการรหัสผ่านเพื่อบันทึกข้อมูลและลงชื่อเข้าใช้เร็วขึ้นในครั้งถัดไป"</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="5220979185879006862">"สร้างพาสคีย์สำหรับ <xliff:g id="APPNAME">%1$s</xliff:g> ไหม"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"บันทึกรหัสผ่านสำหรับ <xliff:g id="APPNAME">%1$s</xliff:g> ไหม"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"บันทึกข้อมูลการลงชื่อเข้าใช้สำหรับ <xliff:g id="APPNAME">%1$s</xliff:g> ไหม"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"คุณสามารถใช้ <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> ของ <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> ในอุปกรณ์ใดก็ได้ โดยระบบจะบันทึกลงใน <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> สำหรับ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</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="6372952459932674632">"สร้างพาสคีย์ในอุปกรณ์อื่นไหม"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"สร้างพาสคีย์ในอุปกรณ์อื่นไหม"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"ใช้ <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> สำหรับการลงชื่อเข้าใช้ทั้งหมดใช่ไหม"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"เครื่องมือจัดการรหัสผ่านนี้จะจัดเก็บรหัสผ่านและพาสคีย์ไว้เพื่อช่วยให้คุณลงชื่อเข้าใช้ได้โดยง่าย"</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"เครื่องมือจัดการรหัสผ่านนี้จะจัดเก็บรหัสผ่านและพาสคีย์ไว้เพื่อช่วยให้คุณลงชื่อเข้าใช้ได้โดยง่าย"</string>
<string name="set_as_default" msgid="4415328591568654603">"ตั้งเป็นค่าเริ่มต้น"</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>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index d3328a5..633c3a0 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Kanselahin"</string>
<string name="string_continue" msgid="1346732695941131882">"Magpatuloy"</string>
<string name="string_more_options" msgid="7990658711962795124">"Higit pang opsyon"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Gumawa sa ibang lugar"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"I-save sa ibang lugar"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Gumamit ng ibang device"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"I-save sa ibang device"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Mas ligtas gamit ang mga passkey"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Gamit ang mga passkey, hindi mo na kailangang gumawa o tumanda ng mga komplikadong password"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ang mga passkey ay mga naka-encrypt na digital na susi na ginagawa mo gamit ang iyong fingerprint, mukha, o lock ng screen"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Sine-save ang mga ito sa isang password manager para makapag-sign in ka sa iba pang device"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Piliin kung saan <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"gawin ang iyong mga passkey"</string>
- <string name="save_your_password" msgid="6597736507991704307">"i-save ang iyong password"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"i-save ang iyong impormasyon sa pag-sign in"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Pumili ng password manger para ma-save ang iyong impormasyon at makapag-sign in nang mas mabilis sa susunod na pagkakataon."</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"Piliin kung saan mo ise-save ang iyong <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Pumili ng password manger para ma-save ang iyong impormasyon at makapag-sign in nang mas mabilis sa susunod na pagkakataon"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Gumawa ng passkey para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"I-save ang password para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"I-save ang impormasyon sa pag-sign in para sa <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Magagamit mo ang iyong <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> sa anumang device. Naka-save ito sa <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> para sa <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"passkey"</string>
<string name="password" msgid="6738570945182936667">"password"</string>
+ <string name="passkeys" msgid="5733880786866559847">"mga passkey"</string>
+ <string name="passwords" msgid="5419394230391253816">"mga password"</string>
<string name="sign_ins" msgid="4710739369149469208">"mga sign-in"</string>
<string name="sign_in_info" msgid="2627704710674232328">"impormasyon sa pag-sign in"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"I-save ang <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> sa"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Gumawa ng passkey sa ibang device?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Gumawa ng passkey sa ibang device?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Gamitin ang <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> para sa lahat ng iyong pag-sign in?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Iso-store ng password manager na ito ang iyong mga password at passkey para madali kang makapag-sign in."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Iso-store ng password manager na ito ang iyong mga password at passkey para madali kang makapag-sign in"</string>
<string name="set_as_default" msgid="4415328591568654603">"Itakda bilang default"</string>
<string name="use_once" msgid="9027366575315399714">"Gamitin nang isang beses"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> (na) password • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> (na) passkey"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index c315a20..3627e6c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"İptal"</string>
<string name="string_continue" msgid="1346732695941131882">"Devam"</string>
<string name="string_more_options" msgid="7990658711962795124">"Diğer seçenekler"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Başka bir yerde oluşturun"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Başka bir yere kaydedin"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Başka bir cihaz kullan"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Başka bir cihaza kaydet"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Şifre anahtarlarıyla daha yüksek güvenlik"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Şifre anahtarı kullandığınızda karmaşık şifreler oluşturmanız veya bunları hatırlamanız gerekmez"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Şifre anahtarları; parmak iziniz, yüzünüz veya ekran kilidinizi kullanarak oluşturduğunuz şifrelenmiş dijital anahtarlardır"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Diğer cihazlarda oturum açabilmeniz için şifre anahtarları bir şifre yöneticisine kaydedilir"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> yerini seçin"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"şifre anahtarlarınızı oluşturun"</string>
- <string name="save_your_password" msgid="6597736507991704307">"şifrenizi kaydedin"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"oturum açma bilgilerinizi kaydedin"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Bilgilerinizi kaydedip bir dahaki sefere daha hızlı oturum açmak için bir şifre yöneticisi seçin."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre anahtarı oluşturulsun mu?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> için şifre kaydedilsin mi?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> için oturum açma bilgileri kaydedilsin mi?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> herhangi bir cihazda kullanılabilir. <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> için <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> içine kaydedilir."</string>
<string name="passkey" msgid="632353688396759522">"şifre anahtarı"</string>
<string name="password" msgid="6738570945182936667">"şifre"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"oturum aç"</string>
<string name="sign_in_info" msgid="2627704710674232328">"oturum açma bilgileri"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Şuraya kaydet: <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Başka bir cihazda şifre anahtarı oluşturulsun mu?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Tüm oturum açma işlemlerinizde <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kullanılsın mı?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Bu şifre yöneticisi, şifrelerinizi ve şifre anahtarlarınızı saklayarak kolayca oturum açmanıza yardımcı olur."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Varsayılan olarak ayarla"</string>
<string name="use_once" msgid="9027366575315399714">"Bir kez kullanın"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> şifre • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> şifre anahtarı"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index cb33665..49ef6c1 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Скасувати"</string>
<string name="string_continue" msgid="1346732695941131882">"Продовжити"</string>
<string name="string_more_options" msgid="7990658711962795124">"Інші опції"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Створити в іншому місці"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Зберегти в іншому місці"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Скористатись іншим пристроєм"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Зберегти на іншому пристрої"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Ключі доступу покращують безпеку"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Маючи ключі доступу, не потрібно створювати чи запам’ятовувати складні паролі"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Ключі доступу – це зашифровані цифрові ключі, які ви створюєте за допомогою відбитка пальця, фейс-контролю чи засобу розблокування екрана"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Вони зберігаються в менеджері паролів, тож ви можете входити на інших пристроях"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Виберіть, де <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"створювати ключі доступу"</string>
- <string name="save_your_password" msgid="6597736507991704307">"зберегти пароль"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"зберегти дані для входу"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Виберіть менеджер паролів, щоб зберігати свої дані й надалі входити в облікові записи швидше."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Створити ключ доступу для додатка <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Зберегти пароль для додатка <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Зберегти дані для входу для додатка <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Ви зможете використовувати <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> додатка <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> на будь-якому пристрої. Ці дані зберігаються в сервісі <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> для користувача <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"ключ доступу"</string>
<string name="password" msgid="6738570945182936667">"пароль"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"Створити ключ доступу на іншому пристрої?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Використовувати сервіс <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> в усіх випадках входу?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Цей менеджер паролів зберігатиме ваші паролі та ключі доступу, щоб ви могли легко входити в облікові записи."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Вибрати за умовчанням"</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>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 91e8ee7..8ceb842 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"منسوخ کریں"</string>
<string name="string_continue" msgid="1346732695941131882">"جاری رکھیں"</string>
<string name="string_more_options" msgid="7990658711962795124">"مزید اختیارات"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"دوسرے مقام میں تخلیق کریں"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"دوسرے مقام میں محفوظ کریں"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"کوئی دوسرا آلہ استعمال کریں"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"دوسرے آلے میں محفوظ کریں"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"پاس کیز کے ساتھ زیادہ محفوظ"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"پاس کیز کے ساتھ آپ کو پیچیدہ پاس ورڈز تخلیق کرنے یا انہیں یاد رکھنے کی ضرورت نہیں ہے"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"پاس کیز مرموز کردہ ڈیجیٹل کلیدیں ہیں جنہیں آپ اپنا فنگر پرنٹ، چہرہ یا اسکرین لاک استعمال کرتے ہوئے تخلیق کرتے ہیں"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"ان کو پاس ورڈ مینیجر میں محفوظ کیا جاتا ہے تاکہ آپ دوسرے آلات پر سائن ان کر سکیں"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> کی جگہ منتخب کریں"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"اپنی پاس کیز تخلیق کریں"</string>
- <string name="save_your_password" msgid="6597736507991704307">"اپنا پاس ورڈ محفوظ کریں"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"اپنے سائن ان کی معلومات محفوظ کریں"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"اپنی معلومات کو محفوظ کرنے اور اگلی بار تیز سائن کے لیے پاس ورڈ مینیجر منتخب کریں۔"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> کے لیے پاس کی تخلیق کریں؟"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> کے لیے پاس ورڈ کو محفوظ کریں؟"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> کے لیے سائن ان کی معلومات محفوظ کریں؟"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"آپ کسی بھی آلے پر اپنا <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> استعمال کر سکتے ہیں۔ یہ <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> کے لیے <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> میں محفوظ کیا جاتا ہے۔"</string>
<string name="passkey" msgid="632353688396759522">"پاس کی"</string>
<string name="password" msgid="6738570945182936667">"پاس ورڈ"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"کسی اور آلے میں پاس کی تخلیق کریں؟"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"اپنے سبھی سائن انز کے لیے <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> کا استعمال کریں؟"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"یہ پاس ورڈ مینیجر آپ کے پاس ورڈز اور پاس کیز کو آسانی سے سائن ان کرنے میں آپ کی مدد کرنے کے لیے اسٹور کرے گا۔"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"بطور ڈیفالٹ سیٹ کریں"</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>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index cf51f03..9233a53 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"Bekor qilish"</string>
<string name="string_continue" msgid="1346732695941131882">"Davom etish"</string>
<string name="string_more_options" msgid="7990658711962795124">"Boshqa parametrlar"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Boshqa joyda yaratish"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Boshqa joyga saqlash"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Boshqa qurilmadan foydalaning"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Boshqa qurilmaga saqlash"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Kalitlar orqali qulay"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Kodlar yordami tufayli murakkab parollarni yaratish va eslab qolish shart emas"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Kodlar – bu barmoq izi, yuz yoki ekran qulfi yordamida yaratilgan shifrlangan raqamli identifikator."</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Ular parollar menejerida saqlanadi va ulardan boshqa qurilmalarda hisobga kirib foydalanish mumkin"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"<xliff:g id="CREATETYPES">%1$s</xliff:g> joyini tanlang"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"kodlar yaratish"</string>
- <string name="save_your_password" msgid="6597736507991704307">"Parolni saqlash"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"kirish axborotini saqlang"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Maʼlumotlaringizni saqlash va keyingi safar tez kirish uchun parollar menejerini tanlang"</string>
+ <string name="choose_provider_title" msgid="8870795677024868108">"<xliff:g id="CREATETYPES">%1$s</xliff:g> qayerga saqlanishini tanlang"</string>
+ <string name="choose_provider_body" msgid="4967074531845147434">"Maʼlumotlaringizni saqlash va keyingi safar tez kirish uchun parollar menejerini tanlang"</string>
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun kod yaratilsinmi?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun parol saqlansinmi?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"<xliff:g id="APPNAME">%1$s</xliff:g> uchun kirish maʼlumoti saqlansinmi?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> istalgan qurilmada ishlatilishi mumkin. U <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> uchun <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> xizmatiga saqlandi"</string>
<string name="passkey" msgid="632353688396759522">"kalit"</string>
<string name="password" msgid="6738570945182936667">"parol"</string>
+ <string name="passkeys" msgid="5733880786866559847">"kodlar"</string>
+ <string name="passwords" msgid="5419394230391253816">"parollar"</string>
<string name="sign_ins" msgid="4710739369149469208">"kirishlar"</string>
<string name="sign_in_info" msgid="2627704710674232328">"kirish maʼlumoti"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>ni saqlash"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Boshqa qurilmada kod yaratilsinmi?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"Boshqa qurilmada kod yaratilsinmi?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Hamma kirishlarda <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> ishlatilsinmi?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Bu parollar menejerida hisobga oson kirishga yordam beruvchi parol va kalitlar saqlanadi."</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"Bu parollar menejerida hisobga oson kirishga yordam beruvchi parol va kalitlar saqlanadi"</string>
<string name="set_as_default" msgid="4415328591568654603">"Birlamchi deb belgilash"</string>
<string name="use_once" msgid="9027366575315399714">"Bir marta ishlatish"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> ta parol • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> ta kod"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 5102625..94111a7 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Huỷ"</string>
<string name="string_continue" msgid="1346732695941131882">"Tiếp tục"</string>
<string name="string_more_options" msgid="7990658711962795124">"Tuỳ chọn khác"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Tạo ở vị trí khác"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Lưu vào vị trí khác"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Dùng thiết bị khác"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Lưu vào thiết bị khác"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"An toàn hơn nhờ mã xác thực"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Mã xác thực giúp bạn tránh được việc phải tạo và ghi nhớ mật khẩu phức tạp"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Mã xác thực là các khoá kỹ thuật số được mã hoá mà bạn tạo bằng cách dùng vân tay, khuôn mặt hoặc phương thức khoá màn hình của mình"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Thông tin này được lưu vào trình quản lý mật khẩu nên bạn có thể đăng nhập trên các thiết bị khác"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Chọn vị trí <xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"tạo mã xác thực"</string>
- <string name="save_your_password" msgid="6597736507991704307">"lưu mật khẩu của bạn"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"lưu thông tin đăng nhập của bạn"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Hãy chọn một trình quản lý mật khẩu để lưu thông tin của bạn và đăng nhập nhanh hơn trong lần tới."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Tạo mã xác thực cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Lưu mật khẩu cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Lưu thông tin đăng nhập cho <xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Bạn có thể sử dụng <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> <xliff:g id="APPDOMAINNAME">%1$s</xliff:g> trên mọi thiết bị. Thông tin này được lưu vào <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> cho <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>."</string>
<string name="passkey" msgid="632353688396759522">"mã xác thực"</string>
<string name="password" msgid="6738570945182936667">"mật khẩu"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"thông tin đăng nhập"</string>
<string name="sign_in_info" msgid="2627704710674232328">"thông tin đăng nhập"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Lưu <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> vào"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Tạo mã xác thực trong một thiết bị khác?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Dùng <xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> cho mọi thông tin đăng nhập của bạn?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Trình quản lý mật khẩu này sẽ lưu trữ mật khẩu và mã xác thực của bạn để bạn dễ dàng đăng nhập."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Đặt làm mặc định"</string>
<string name="use_once" msgid="9027366575315399714">"Dùng một lần"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> mật khẩu • <xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g> mã xác thực"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index fcc8b02..1fc42bd 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"取消"</string>
<string name="string_continue" msgid="1346732695941131882">"继续"</string>
<string name="string_more_options" msgid="7990658711962795124">"更多选项"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"在另一位置创建"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"保存到另一位置"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"使用另一台设备"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"保存到其他设备"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"通行密钥可提高安全性"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"借助通行密钥,您无需创建或记住复杂的密码"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"通行密钥是指您使用您的指纹、面孔或屏锁方式创建的加密数字钥匙"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"系统会将通行密钥保存到密码管理工具中,以便您在其他设备上登录"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"选择<xliff:g id="CREATETYPES">%1$s</xliff:g>的位置"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"创建通行密钥"</string>
- <string name="save_your_password" msgid="6597736507991704307">"保存您的密码"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"保存您的登录信息"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"请选择一款密码管理工具来保存您的信息,以便下次更快地登录。"</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"要为“<xliff:g id="APPNAME">%1$s</xliff:g>”创建通行密钥吗?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"要保存“<xliff:g id="APPNAME">%1$s</xliff:g>”的密码吗?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"要保存“<xliff:g id="APPNAME">%1$s</xliff:g>”的登录信息吗?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"您可以在任意设备上使用“<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>”<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>。系统会将此信息保存到<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>,以供<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>使用。"</string>
<string name="passkey" msgid="632353688396759522">"通行密钥"</string>
<string name="password" msgid="6738570945182936667">"密码"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<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="6372952459932674632">"在其他设备上创建通行密钥?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"将“<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>”用于您的所有登录信息?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"此密码管理工具将会存储您的密码和通行密钥,以帮助您轻松登录。"</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"设为默认项"</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>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 7c150bd..276b936 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"取消"</string>
<string name="string_continue" msgid="1346732695941131882">"繼續"</string>
<string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"在其他位置建立"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"儲存至其他位置"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"改用其他裝置"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"儲存至其他裝置"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密鑰確保帳戶安全"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密鑰,您便無需建立或記住複雜的密碼"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密鑰是您使用指紋、面孔或螢幕鎖定時建立的加密數碼鑰匙"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"密鑰已儲存至密碼管理工具,方便您在其他裝置上登入"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"選擇「<xliff:g id="CREATETYPES">%1$s</xliff:g>」的位置"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"建立密鑰"</string>
- <string name="save_your_password" msgid="6597736507991704307">"儲存密碼"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"儲存登入資料"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"選取密碼管理工具即可儲存自己的資料,縮短下次登入的時間。"</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="5220979185879006862">"要為「<xliff:g id="APPNAME">%1$s</xliff:g>」建立密鑰嗎?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"要儲存「<xliff:g id="APPNAME">%1$s</xliff:g>」的密碼嗎?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"要儲存「<xliff:g id="APPNAME">%1$s</xliff:g>」的登入資料嗎?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"您可以在任何裝置上使用「<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>」<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>。系統會將此資料儲存至「<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>」,供「<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>」使用"</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="6372952459932674632">"要在另一部裝置上建立密鑰嗎?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"要在其他裝置上建立密碼金鑰嗎?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"要將「<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>」用於所有的登入資料嗎?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"此密碼管理工具將儲存您的密碼和密鑰,協助您輕鬆登入。"</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"這個密碼管理工具會儲存密碼和密碼金鑰,協助你輕鬆登入"</string>
<string name="set_as_default" msgid="4415328591568654603">"設定為預設"</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>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index a8b19c8..910756e 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -5,31 +5,25 @@
<string name="string_cancel" msgid="6369133483981306063">"取消"</string>
<string name="string_continue" msgid="1346732695941131882">"繼續"</string>
<string name="string_more_options" msgid="7990658711962795124">"更多選項"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"在其他位置建立"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"儲存至其他位置"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"改用其他裝置"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"儲存至其他裝置"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"使用密碼金鑰確保帳戶安全"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"有了密碼金鑰,就不必建立或記住複雜的密碼"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"密碼金鑰是你利用指紋、臉孔或螢幕鎖定功能建立的加密數位金鑰"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"密碼金鑰會儲存到密碼管理工具,方便你在其他裝置上登入"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"選擇「<xliff:g id="CREATETYPES">%1$s</xliff:g>」的位置"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"建立金鑰密碼"</string>
- <string name="save_your_password" msgid="6597736507991704307">"儲存密碼"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"儲存登入資訊"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"選取密碼管理工具即可儲存你的資訊,下次就能更快登入。"</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="5220979185879006862">"要為「<xliff:g id="APPNAME">%1$s</xliff:g>」建立密碼金鑰嗎?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"要儲存「<xliff:g id="APPNAME">%1$s</xliff:g>」的密碼嗎?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"要儲存「<xliff:g id="APPNAME">%1$s</xliff:g>」的登入資訊嗎?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"你可以在任何裝置上使用「<xliff:g id="APPDOMAINNAME">%1$s</xliff:g>」<xliff:g id="CREDENTIALTYPES">%2$s</xliff:g>。這項資料會儲存至 <xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g>,以供 <xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g> 使用。"</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="6372952459932674632">"要在另一部裝置上建立密碼金鑰嗎?"</string>
+ <string name="create_passkey_in_other_device_title" msgid="9195411122362461390">"要在其他裝置上建立密碼金鑰嗎?"</string>
<string name="use_provider_for_all_title" msgid="4201020195058980757">"要將「<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g>」用於所有的登入資訊嗎?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"這個密碼管理工具會儲存你的密碼和密碼金鑰,協助你輕鬆登入。"</string>
+ <string name="use_provider_for_all_description" msgid="8466427781848268490">"這個密碼管理工具會儲存密碼和密碼金鑰,協助你輕鬆登入"</string>
<string name="set_as_default" msgid="4415328591568654603">"設為預設"</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>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index f17c1df..ab56435 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -5,31 +5,31 @@
<string name="string_cancel" msgid="6369133483981306063">"Khansela"</string>
<string name="string_continue" msgid="1346732695941131882">"Qhubeka"</string>
<string name="string_more_options" msgid="7990658711962795124">"Okunye okungakukhethwa kukho"</string>
- <string name="string_create_in_another_place" msgid="1033635365843437603">"Sungula kwenye indawo"</string>
- <string name="string_save_to_another_place" msgid="7590325934591079193">"Londoloza kwenye indawo"</string>
- <string name="string_use_another_device" msgid="8754514926121520445">"Sebenzisa enye idivayisi"</string>
- <string name="string_save_to_another_device" msgid="1959562542075194458">"Londoloza kwenye idivayisi"</string>
<string name="passkey_creation_intro_title" msgid="4251037543787718844">"Iphephe ngokhiye bokudlula"</string>
<string name="passkey_creation_intro_body_password" msgid="8825872426579958200">"Ngokhiye wokudlula, awudingi ukusungula noma ukukhumbula amaphasiwedi ayinkimbinkimbi"</string>
<string name="passkey_creation_intro_body_fingerprint" msgid="7331338631826254055">"Okhiye bokungena bangokhiye bedijithali ababethelwe obasungula usebenzisa isigxivizo somunwe sakho, ubuso, noma ukukhiya isikrini"</string>
<string name="passkey_creation_intro_body_device" msgid="1203796455762131631">"Okhiye bokudlula balondolozwa kusiphathi sephasiwedi, ukuze ukwazi ukungena ngemvume kwamanye amadivayisi"</string>
- <string name="choose_provider_title" msgid="7245243990139698508">"Khetha lapho onga-<xliff:g id="CREATETYPES">%1$s</xliff:g>"</string>
- <string name="create_your_passkeys" msgid="8901224153607590596">"sungula okhiye bakho bokudlula"</string>
- <string name="save_your_password" msgid="6597736507991704307">"Londoloza iphasiwedi yakho"</string>
- <string name="save_your_sign_in_info" msgid="7213978049817076882">"londoloza ulwazi lwakho lokungena ngemvume"</string>
- <string name="choose_provider_body" msgid="4384188171872005547">"Khetha isiphathi sephasiwedi ukuze ulondoloze ulwazi lwakho futhi ungene ngemvume ngokushesha ngesikhathi esizayo."</string>
+ <!-- no translation found for choose_provider_title (8870795677024868108) -->
+ <skip />
+ <!-- no translation found for choose_provider_body (4967074531845147434) -->
+ <skip />
<string name="choose_create_option_passkey_title" msgid="5220979185879006862">"Sungula ukhiye wokudlula we-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_password_title" msgid="7097275038523578687">"Londolozela amaphasiwedi ye-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
<string name="choose_create_option_sign_in_title" msgid="4124872317613421249">"Londoloza ulwazi lokungena lwe-<xliff:g id="APPNAME">%1$s</xliff:g>?"</string>
- <string name="choose_create_option_description" msgid="5531335144879100664">"Ungasebenzisa i-<xliff:g id="APPDOMAINNAME">%1$s</xliff:g> <xliff:g id="CREDENTIALTYPES">%2$s</xliff:g> yakho kunoma iyiphi idivayisi. Ilondolozwe ku-<xliff:g id="PROVIDERINFODISPLAYNAME">%3$s</xliff:g> ye-<xliff:g id="CREATEINFODISPLAYNAME">%4$s</xliff:g>"</string>
<string name="passkey" msgid="632353688396759522">"ukhiye wokudlula"</string>
<string name="password" msgid="6738570945182936667">"iphasiwedi"</string>
+ <!-- no translation found for passkeys (5733880786866559847) -->
+ <skip />
+ <!-- no translation found for passwords (5419394230391253816) -->
+ <skip />
<string name="sign_ins" msgid="4710739369149469208">"ukungena ngemvume"</string>
<string name="sign_in_info" msgid="2627704710674232328">"ulwazi lokungena ngemvume"</string>
<string name="save_credential_to_title" msgid="3172811692275634301">"Londoloza i-<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> ku-"</string>
- <string name="create_passkey_in_other_device_title" msgid="6372952459932674632">"Sungula ukhiye wokudlula kwenye idivayisi?"</string>
+ <!-- no translation found for create_passkey_in_other_device_title (9195411122362461390) -->
+ <skip />
<string name="use_provider_for_all_title" msgid="4201020195058980757">"Sebenzisa i-<xliff:g id="PROVIDERINFODISPLAYNAME">%1$s</xliff:g> kukho konke ukungena kwakho ngemvume?"</string>
- <string name="use_provider_for_all_description" msgid="6560593199974037820">"Lesi siphathi sephasiwedi sizogcina amaphasiwedi akho nezikhiye zokungena ukuze zikusize ungene ngemvume kalula."</string>
+ <!-- no translation found for use_provider_for_all_description (8466427781848268490) -->
+ <skip />
<string name="set_as_default" msgid="4415328591568654603">"Setha njengokuzenzakalelayo"</string>
<string name="use_once" msgid="9027366575315399714">"Sebenzisa kanye"</string>
<string name="more_options_usage_passwords_passkeys" msgid="3470113942332934279">"Amaphasiwedi angu-<xliff:g id="PASSWORDSNUMBER">%1$s</xliff:g> • okhiye bokudlula abangu-<xliff:g id="PASSKEYSNUMBER">%2$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 81505e1..d6909719 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -11,13 +11,34 @@
<string name="string_continue">Continue</string>
<!-- This is a label for a button that links to different places where the user can save their passkeys. [CHAR LIMIT=20] -->
<string name="string_more_options">More options</string>
+ <!-- This is a label for a button that links to additional information about passkeys. [CHAR LIMIT=20] -->
+ <string name="string_learn_more">Learn more</string>
<!-- This string introduces passkeys to the users for the first time they use this method. Tip: to avoid gendered language patterns, this header could be translated as if the original string were "More safety with passkeys". [CHAR LIMIT=200] -->
<string name="passkey_creation_intro_title">Safer with passkeys</string>
- <!-- These strings highlight passkey benefits. [CHAR LIMIT=200] -->
+ <!-- This string highlight passkey benefits related with the password. [CHAR LIMIT=200] -->
<string name="passkey_creation_intro_body_password">With passkeys, you don’t need to create or remember complex passwords</string>
+ <!-- This string highlight passkey benefits related with encrypted. [CHAR LIMIT=200] -->
<string name="passkey_creation_intro_body_fingerprint">Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock</string>
+ <!-- This string highlight passkey benefits related with signing with other devices. [CHAR LIMIT=200] -->
<string name="passkey_creation_intro_body_device">They are saved to a password manager, so you can sign in on other devices</string>
-
+ <!-- This string introduces passkeys in more detail to the users for the first time they use this method. [CHAR LIMIT=200] -->
+ <string name="more_about_passkeys_title">More about passkeys</string>
+ <!-- Title for subsection of "Learn more about passkeys" screen about passwordless technology. [CHAR LIMIT=80] -->
+ <string name="passwordless_technology_title">Passwordless technology</string>
+ <!-- Detail for subsection of "Learn more about passkeys" screen about passwordless technology. [CHAR LIMIT=500] -->
+ <string name="passwordless_technology_detail">Passkeys allow you to sign in without relying on passwords. You just need to use your fingerprint, face recognition, PIN, or swipe pattern to verify your identity and create a passkey.</string>
+ <!-- Title for subsection of "Learn more about passkeys" screen about public key cryptography. [CHAR LIMIT=80] -->
+ <string name="public_key_cryptography_title">Public key cryptography</string>
+ <!-- Detail for subsection of "Learn more about passkeys" screen about public key cryptography. [CHAR LIMIT=500] -->
+ <string name="public_key_cryptography_detail">Based on FIDO Alliance (which includes Google, Apple, Microsoft, and more) and W3C standards, passkeys use cryptographic key pairs. Unlike the username and string of characters we use for passwords, a private-public key pair is created for an app or website. The private key is safely stored on your device or password manager and it confirms your identity. The public key is shared with the app or website server. With corresponding keys, you can instantly register and sign in.</string>
+ <!-- Title for subsection of "Learn more about passkeys" screen about improved account security. [CHAR LIMIT=80] -->
+ <string name="improved_account_security_title">Improved account security</string>
+ <!-- Detail for subsection of "Learn more about passkeys" screen about improved account security. [CHAR LIMIT=500] -->
+ <string name="improved_account_security_detail">Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder.</string>
+ <!-- Title for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=80] -->
+ <string name="seamless_transition_title">Seamless transition</string>
+ <!-- Detail for subsection of "Learn more about passkeys" screen about seamless transition. [CHAR LIMIT=500] -->
+ <string name="seamless_transition_detail">As we move towards a passwordless future, passwords will still be available alongside passkeys.</string>
<!-- This appears as the title of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
<string name="choose_provider_title">Choose where to save your <xliff:g id="createTypes" example="passkeys">%1$s</xliff:g></string>
<!-- This appears as the description body of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 7d43364..0761b64 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -99,10 +99,20 @@
)
}
- fun onCancel() {
+ // The dialog is canceled by the user.
+ fun onUserCancel() {
+ onCancel(BaseDialogResult.RESULT_CODE_DIALOG_USER_CANCELED)
+ }
+
+ // The dialog is canceled because we launched into settings.
+ fun onSettingLaunchCancel() {
+ onCancel(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION)
+ }
+
+ private fun onCancel(cancelCode: Int) {
val resultData = Bundle()
BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData)
- resultReceiver?.send(BaseDialogResult.RESULT_CODE_DIALOG_CANCELED, resultData)
+ resultReceiver?.send(cancelCode, resultData)
}
fun onOptionSelected(
@@ -414,7 +424,7 @@
credentialData,
// TODO: populate with actual data
/*candidateQueryData=*/ Bundle(),
- /*requireSystemProvider=*/ false
+ /*isSystemProviderRequired=*/ false
),
"com.google.android.youtube"
)
@@ -429,7 +439,7 @@
data,
// TODO: populate with actual data
/*candidateQueryData=*/ Bundle(),
- /*requireSystemProvider=*/ false
+ /*isSystemProviderRequired=*/ false
),
"com.google.android.youtube"
)
@@ -443,7 +453,7 @@
"other-sign-ins",
data,
/*candidateQueryData=*/ Bundle(),
- /*requireSystemProvider=*/ false
+ /*isSystemProviderRequired=*/ false
),
"com.google.android.youtube"
)
@@ -457,7 +467,7 @@
)
.addGetCredentialOption(
GetCredentialOption(
- TYPE_PUBLIC_KEY_CREDENTIAL, Bundle(), Bundle(), /*requireSystemProvider=*/ false)
+ TYPE_PUBLIC_KEY_CREDENTIAL, Bundle(), Bundle(), /*isSystemProviderRequired=*/ false)
)
.build(),
"com.google.android.youtube"
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 09f9b5e..d9e4dc8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -269,7 +269,7 @@
val createCredentialRequest = requestInfo.createCredentialRequest
val createCredentialRequestJetpack = createCredentialRequest?.let {
CreateCredentialRequest.createFrom(
- it.type, it.credentialData, it.candidateQueryData, it.requireSystemProvider()
+ it.type, it.credentialData, it.candidateQueryData, it.isSystemProviderRequired()
)
}
when (createCredentialRequestJetpack) {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 498f0a1..1e1c833 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -70,7 +70,7 @@
when (uiState.currentScreenState) {
CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
onConfirm = viewModel::onConfirmIntro,
- onCancel = viewModel::onCancel,
+ onLearnMore = viewModel::onLearnMore,
)
CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
requestDisplayInfo = uiState.requestDisplayInfo,
@@ -115,7 +115,10 @@
activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!,
onOptionSelected = viewModel::onEntrySelected,
onConfirm = viewModel::onConfirmEntrySelected,
- onCancel = viewModel::onCancel,
+ )
+ CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO -> MoreAboutPasskeysIntroCard(
+ onBackPasskeyIntroButtonSelected =
+ viewModel::onBackPasskeyIntroButtonSelected,
)
}
} else if (uiState.selectedEntry != null && !uiState.providerActivityPending) {
@@ -136,7 +139,7 @@
@Composable
fun ConfirmationCard(
onConfirm: () -> Unit,
- onCancel: () -> Unit,
+ onLearnMore: () -> Unit,
) {
ContainerCard() {
Column() {
@@ -223,8 +226,8 @@
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
ActionButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
+ stringResource(R.string.string_learn_more),
+ onClick = onLearnMore
)
ConfirmButton(
stringResource(R.string.string_continue),
@@ -396,8 +399,7 @@
)
}
},
- colors = TopAppBarDefaults.smallTopAppBarColors
- (containerColor = Color.Transparent),
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
modifier = Modifier.padding(top = 12.dp)
)
Divider(
@@ -475,7 +477,8 @@
Icons.Outlined.NewReleases,
contentDescription = null,
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
- .padding(all = 24.dp)
+ .padding(all = 24.dp),
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
)
TextOnSurface(
text = stringResource(
@@ -634,14 +637,13 @@
activeRemoteEntry: EntryInfo,
onOptionSelected: (EntryInfo) -> Unit,
onConfirm: () -> Unit,
- onCancel: () -> Unit,
) {
ContainerCard() {
Column() {
Icon(
painter = painterResource(R.drawable.ic_other_devices),
contentDescription = null,
- tint = Color.Unspecified,
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
.padding(all = 24.dp).size(32.dp)
)
@@ -673,13 +675,9 @@
color = Color.Transparent
)
Row(
- horizontalArrangement = Arrangement.SpaceBetween,
+ horizontalArrangement = Arrangement.End,
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
- ActionButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
- )
ConfirmButton(
stringResource(R.string.string_continue),
onClick = onConfirm
@@ -696,6 +694,92 @@
@OptIn(ExperimentalMaterial3Api::class)
@Composable
+fun MoreAboutPasskeysIntroCard(
+ onBackPasskeyIntroButtonSelected: () -> Unit,
+) {
+ ContainerCard() {
+ Column() {
+ TopAppBar(
+ title = {
+ TextOnSurface(
+ text =
+ stringResource(
+ R.string.more_about_passkeys_title),
+ style = MaterialTheme.typography.titleMedium,
+ )
+ },
+ navigationIcon = {
+ IconButton(
+ onClick = onBackPasskeyIntroButtonSelected
+ ) {
+ Icon(
+ Icons.Filled.ArrowBack,
+ stringResource(R.string.accessibility_back_arrow_button)
+ )
+ }
+ },
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
+ modifier = Modifier.padding(top = 12.dp)
+ )
+ Column(
+ modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 68.dp)
+ ) {
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.passwordless_technology_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.passwordless_technology_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.public_key_cryptography_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.public_key_cryptography_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.improved_account_security_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.improved_account_security_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.seamless_transition_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.seamless_transition_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 24.dp)
+ )
+ }
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
fun PrimaryCreateOptionRow(
requestDisplayInfo: RequestDisplayInfo,
entryInfo: EntryInfo,
@@ -889,7 +973,8 @@
Icon(
Icons.Filled.Add,
contentDescription = null,
- modifier = Modifier.padding(start = 16.dp)
+ modifier = Modifier.padding(start = 16.dp),
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
)
},
label = {
@@ -923,8 +1008,8 @@
Icon(
painter = painterResource(R.drawable.ic_other_devices),
contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.padding(start = 18.dp)
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+ modifier = Modifier.padding(start = 10.dp)
)
},
label = {
@@ -932,7 +1017,7 @@
TextOnSurfaceVariant(
text = stringResource(R.string.another_device),
style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
+ modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
.align(alignment = Alignment.CenterHorizontally),
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
index ac84503..a9b1d332 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
@@ -122,6 +122,12 @@
)
}
+ fun onBackPasskeyIntroButtonSelected() {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.PASSKEY_INTRO,
+ )
+ }
+
fun onEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) {
uiState = uiState.copy(
currentScreenState = if (
@@ -141,15 +147,21 @@
}
fun onDisabledProvidersSelected() {
- credManRepo.onCancel()
+ credManRepo.onSettingLaunchCancel()
dialogResult.tryEmit(DialogResult(ResultState.LAUNCH_SETTING_CANCELED))
}
fun onCancel() {
- credManRepo.onCancel()
+ credManRepo.onUserCancel()
dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED))
}
+ fun onLearnMore() {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO,
+ )
+ }
+
fun onChangeDefaultSelected() {
uiState = uiState.copy(
currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 97477a7..957488f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -91,6 +91,7 @@
/** The name of the current screen. */
enum class CreateScreenState {
PASSKEY_INTRO,
+ MORE_ABOUT_PASSKEYS_INTRO,
PROVIDER_SELECTION,
CREATION_OPTION_SELECTION,
MORE_OPTIONS_SELECTION,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 03f39e1..420b4d5 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -63,6 +63,7 @@
import com.android.credentialmanager.common.material.ModalBottomSheetValue
import com.android.credentialmanager.common.material.rememberModalBottomSheetState
import com.android.credentialmanager.common.ui.ActionButton
+import com.android.credentialmanager.common.ui.ConfirmButton
import com.android.credentialmanager.common.ui.Entry
import com.android.credentialmanager.common.ui.TextOnSurface
import com.android.credentialmanager.common.ui.TextSecondary
@@ -95,7 +96,10 @@
PrimarySelectionCard(
requestDisplayInfo = uiState.requestDisplayInfo,
providerDisplayInfo = uiState.providerDisplayInfo,
+ providerInfoList = uiState.providerInfoList,
+ activeEntry = uiState.activeEntry,
onEntrySelected = viewModel::onEntrySelected,
+ onConfirm = viewModel::onConfirmEntrySelected,
onMoreOptionSelected = viewModel::onMoreOptionSelected,
)
} else {
@@ -133,7 +137,10 @@
fun PrimarySelectionCard(
requestDisplayInfo: RequestDisplayInfo,
providerDisplayInfo: ProviderDisplayInfo,
+ providerInfoList: List<ProviderInfo>,
+ activeEntry: EntryInfo?,
onEntrySelected: (EntryInfo) -> Unit,
+ onConfirm: () -> Unit,
onMoreOptionSelected: () -> Unit,
) {
val sortedUserNameToCredentialEntryList =
@@ -217,13 +224,33 @@
thickness = 24.dp,
color = Color.Transparent
)
+ var totalEntriesCount = sortedUserNameToCredentialEntryList
+ .flatMap{ it.sortedCredentialEntryList}.size + authenticationEntryList
+ .size + providerInfoList.flatMap { it.actionEntryList }.size
+ if (providerDisplayInfo.remoteEntry != null) totalEntriesCount += 1
+ // Row horizontalArrangement differs on only one actionButton(should place on most
+ // left)/only one confirmButton(should place on most right)/two buttons exist the same
+ // time(should be one on the left, one on the right)
Row(
- horizontalArrangement = Arrangement.SpaceBetween,
+ horizontalArrangement =
+ if (totalEntriesCount <= 1 && activeEntry != null) Arrangement.End
+ else if (totalEntriesCount > 1 && activeEntry == null) Arrangement.Start
+ else Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
- ActionButton(
- stringResource(R.string.get_dialog_use_saved_passkey_for),
- onMoreOptionSelected)
+ if (totalEntriesCount > 1) {
+ ActionButton(
+ stringResource(R.string.get_dialog_use_saved_passkey_for),
+ onMoreOptionSelected
+ )
+ }
+ // Only one sign-in options exist
+ if (activeEntry != null) {
+ ConfirmButton(
+ stringResource(R.string.string_continue),
+ onClick = onConfirm
+ )
+ }
}
Divider(
thickness = 18.dp,
@@ -251,7 +278,7 @@
ContainerCard() {
Column() {
TopAppBar(
- colors = TopAppBarDefaults.smallTopAppBarColors(
+ colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
),
title = {
@@ -297,6 +324,12 @@
)
}
}
+ item {
+ Divider(
+ thickness = 8.dp,
+ color = Color.Transparent,
+ )
+ }
// From another device
val remoteEntry = providerDisplayInfo.remoteEntry
if (remoteEntry != null) {
@@ -307,6 +340,13 @@
)
}
}
+ item {
+ Divider(
+ thickness = 1.dp,
+ color = Color.LightGray,
+ modifier = Modifier.padding(top = 16.dp)
+ )
+ }
// Manage sign-ins (action chips)
item {
ActionChips(
@@ -335,7 +375,7 @@
TextSecondary(
text = stringResource(R.string.get_dialog_heading_manage_sign_ins),
- style = MaterialTheme.typography.labelLarge,
+ style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
// TODO: tweak padding.
@@ -343,7 +383,7 @@
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
shape = MaterialTheme.shapes.medium,
) {
- Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
actionChips.forEach {
ActionEntryRow(it, onEntrySelected)
}
@@ -358,7 +398,7 @@
) {
TextSecondary(
text = stringResource(R.string.get_dialog_heading_from_another_device),
- style = MaterialTheme.typography.labelLarge,
+ style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
ContainerCard(
@@ -375,8 +415,8 @@
Icon(
painter = painterResource(R.drawable.ic_other_devices),
contentDescription = null,
- tint = Color.Unspecified,
- modifier = Modifier.padding(start = 18.dp)
+ tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
+ modifier = Modifier.padding(start = 10.dp)
)
},
label = {
@@ -384,7 +424,7 @@
text = stringResource(
R.string.get_dialog_option_headline_use_a_different_device),
style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
+ modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
.align(alignment = Alignment.CenterHorizontally)
)
}
@@ -427,7 +467,7 @@
text = stringResource(
R.string.get_dialog_heading_for_username, perUserNameCredentialEntryList.userName
),
- style = MaterialTheme.typography.labelLarge,
+ style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)
ContainerCard(
@@ -554,7 +594,7 @@
TransparentBackgroundEntry(
icon = {
Image(
- modifier = Modifier.padding(start = 10.dp).size(32.dp),
+ modifier = Modifier.padding(start = 10.dp).size(24.dp),
bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
// TODO: add description.
contentDescription = ""
@@ -565,13 +605,13 @@
TextOnSurfaceVariant(
text = actionEntryInfo.title,
style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(start = 5.dp),
+ modifier = Modifier.padding(start = 8.dp),
)
if (actionEntryInfo.subTitle != null) {
TextSecondary(
text = actionEntryInfo.subTitle,
style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(start = 5.dp),
+ modifier = Modifier.padding(start = 8.dp),
)
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
index 6f0f76b..c72ae72 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
@@ -41,6 +41,7 @@
val currentScreenState: GetScreenState = toGetScreenState(providerInfoList),
val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerInfoList),
val selectedEntry: EntryInfo? = null,
+ val activeEntry: EntryInfo? = toActiveEntry(providerDisplayInfo),
val hidden: Boolean = false,
val providerActivityPending: Boolean = false,
val isNoAccount: Boolean = false,
@@ -73,6 +74,17 @@
}
}
+ fun onConfirmEntrySelected() {
+ val activeEntry = uiState.activeEntry
+ if (activeEntry != null) {
+ onEntrySelected(activeEntry)
+ } else {
+ Log.w("Account Selector",
+ "Illegal state: confirm is pressed but activeEntry isn't set.")
+ dialogResult.tryEmit(DialogResult(ResultState.COMPLETE))
+ }
+ }
+
fun launchProviderUi(
launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
@@ -140,7 +152,7 @@
}
fun onCancel() {
- credManRepo.onCancel()
+ credManRepo.onUserCancel()
dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED))
}
}
@@ -198,6 +210,26 @@
)
}
+private fun toActiveEntry(
+ providerDisplayInfo: ProviderDisplayInfo,
+): EntryInfo? {
+ val sortedUserNameToCredentialEntryList =
+ providerDisplayInfo.sortedUserNameToCredentialEntryList
+ val authenticationEntryList = providerDisplayInfo.authenticationEntryList
+ var activeEntry: EntryInfo? = null
+ if (sortedUserNameToCredentialEntryList
+ .size == 1 && authenticationEntryList.isEmpty()
+ ) {
+ activeEntry = sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList.first()
+ } else if (
+ sortedUserNameToCredentialEntryList
+ .isEmpty() && authenticationEntryList.size == 1
+ ) {
+ activeEntry = authenticationEntryList.first()
+ }
+ return activeEntry
+}
+
private fun toGetScreenState(
providerInfoList: List<ProviderInfo>
): GetScreenState {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt
index 18d5089..5cb8d3b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/developer/GetCredentialRequest.kt
@@ -66,7 +66,7 @@
it.type,
it.credentialRetrievalData,
it.candidateQueryData,
- it.requireSystemProvider()
+ it.isSystemProviderRequired()
)
}
)
diff --git a/packages/PackageInstaller/res/values-af/strings.xml b/packages/PackageInstaller/res/values-af/strings.xml
index 1259eb6..37f2930 100644
--- a/packages/PackageInstaller/res/values-af/strings.xml
+++ b/packages/PackageInstaller/res/values-af/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Program geïnstalleer."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Wil jy hierdie program installeer?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Wil jy hierdie program opdateer?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Program nie geïnstalleer nie."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Die installering van die pakket is geblokkeer."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Program is nie geïnstalleer nie omdat pakket met \'n bestaande pakket bots."</string>
diff --git a/packages/PackageInstaller/res/values-am/strings.xml b/packages/PackageInstaller/res/values-am/strings.xml
index 161878b..83966db 100644
--- a/packages/PackageInstaller/res/values-am/strings.xml
+++ b/packages/PackageInstaller/res/values-am/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"መተግበሪያ ተጭኗል።"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ይህን መተግበሪያ መጫን ይፈልጋሉ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ይህን መተግበሪያ ማዘመን ይፈልጋሉ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"መተግበሪያ አልተጫነም።"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ጥቅሉ እንዳይጫን ታግዷል።"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"እንደ ጥቅል ያልተጫነ መተግበሪያ ከነባር ጥቅል ጋር ይጋጫል።"</string>
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 3e30b74..c7dbf08 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"تم تثبيت التطبيق."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"هل تريد تثبيت هذا التطبيق؟"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"هل تريد تحديث هذا التطبيق؟"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"التطبيق ليس مثبتًا."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"تم حظر تثبيت الحزمة."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"لم يتم تثبيت التطبيق لأن حزمة التثبيت تتعارض مع حزمة حالية."</string>
diff --git a/packages/PackageInstaller/res/values-as/strings.xml b/packages/PackageInstaller/res/values-as/strings.xml
index 6036173..c456268 100644
--- a/packages/PackageInstaller/res/values-as/strings.xml
+++ b/packages/PackageInstaller/res/values-as/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"এপ্ ইনষ্টল কৰা হ’ল।"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"আপুনি এই এপ্টো ইনষ্টল কৰিবলৈ বিচাৰেনে?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"আপুনি এই এপ্টো আপডে’ট কৰিবলৈ বিচাৰেনে?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"এপ্ ইনষ্টল কৰা হোৱা নাই।"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"পেকেজটোৰ ইনষ্টল অৱৰোধ কৰা হৈছে।"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"এপ্টো ইনষ্টল কৰিব পৰা নগ\'ল কাৰণ ইয়াৰ সৈতে আগৰে পৰা থকা এটা পেকেজৰ সংঘাত হৈছে।"</string>
diff --git a/packages/PackageInstaller/res/values-az/strings.xml b/packages/PackageInstaller/res/values-az/strings.xml
index 29c531a..749254a 100644
--- a/packages/PackageInstaller/res/values-az/strings.xml
+++ b/packages/PackageInstaller/res/values-az/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Tətbiq quraşdırılıb."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Bu tətbiqi quraşdırmaq istəyirsiniz?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Bu tətbiqi güncəlləmək istəyirsiniz?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Tətbiq quraşdırılmayıb."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketin quraşdırılması blok edildi."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Bu paketin mövcud paket ilə ziddiyətinə görə tətbiq quraşdırılmadı."</string>
diff --git a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
index 7553ded..b2943a0 100644
--- a/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
+++ b/packages/PackageInstaller/res/values-b+sr+Latn/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Želite da instalirate ovu aplikaciju?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Želite da ažurirate ovu aplikaciju?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa je blokirano."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer je paket neusaglašen sa postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-be/strings.xml b/packages/PackageInstaller/res/values-be/strings.xml
index 078ead9..fa64fa6 100644
--- a/packages/PackageInstaller/res/values-be/strings.xml
+++ b/packages/PackageInstaller/res/values-be/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Праграма ўсталявана."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Усталяваць гэту праграму?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Абнавіць гэту праграму?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Праграма не ўсталявана."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Усталяванне пакета заблакіравана."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Праграма не ўсталявана, таму што пакет канфліктуе з існуючым пакетам."</string>
diff --git a/packages/PackageInstaller/res/values-bg/strings.xml b/packages/PackageInstaller/res/values-bg/strings.xml
index a1c0013..0fb7aa5 100644
--- a/packages/PackageInstaller/res/values-bg/strings.xml
+++ b/packages/PackageInstaller/res/values-bg/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Приложението бе инсталирано."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Искате ли да инсталирате това приложение?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Искате ли да актуализирате това приложение?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Приложението не бе инсталирано."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирането на пакета бе блокирано."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Приложението не бе инсталирано, тъй като пакетът е в конфликт със съществуващ пакет."</string>
diff --git a/packages/PackageInstaller/res/values-bn/strings.xml b/packages/PackageInstaller/res/values-bn/strings.xml
index 2f9dac8..52e5a32 100644
--- a/packages/PackageInstaller/res/values-bn/strings.xml
+++ b/packages/PackageInstaller/res/values-bn/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"অ্যাপটি ইনস্টল করা হয়ে গেছে।"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"আপনি কি এই অ্যাপটি ইনস্টল করতে চান?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"আপনি কি এই অ্যাপটি আপডেট করতে চান?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"অ্যাপটি ইনস্টল করা হয়নি।"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ইনস্টল হওয়া থেকে প্যাকেজটিকে ব্লক করা হয়েছে।"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"আগে থেকেই থাকা একটি প্যাকেজের সাথে প্যাকেজটির সমস্যা সৃষ্টি হওয়ায় অ্যাপটি ইনস্টল করা যায়নি।"</string>
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index 49c180e..01d160b 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje ovog paketa je blokirano."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija nije instalirana jer paket nije usaglašen s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-ca/strings.xml b/packages/PackageInstaller/res/values-ca/strings.xml
index 8947680..7b42cef 100644
--- a/packages/PackageInstaller/res/values-ca/strings.xml
+++ b/packages/PackageInstaller/res/values-ca/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"S\'ha instal·lat l\'aplicació."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vols instal·lar aquesta aplicació?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vols actualitzar aquesta aplicació?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"No s\'ha instal·lat l\'aplicació."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"El paquet s\'ha bloquejat perquè no es pugui instal·lar."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"L\'aplicació no s\'ha instal·lat perquè el paquet entra en conflicte amb un d\'existent."</string>
diff --git a/packages/PackageInstaller/res/values-cs/strings.xml b/packages/PackageInstaller/res/values-cs/strings.xml
index c9f91c3..7e5c881 100644
--- a/packages/PackageInstaller/res/values-cs/strings.xml
+++ b/packages/PackageInstaller/res/values-cs/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikace je nainstalována."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Chcete tuto aplikaci nainstalovat?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete tuto aplikaci aktualizovat?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikaci nelze nainstalovat."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instalace balíčku byla zablokována."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikaci nelze nainstalovat, protože balíček je v konfliktu se stávajícím balíčkem."</string>
diff --git a/packages/PackageInstaller/res/values-da/strings.xml b/packages/PackageInstaller/res/values-da/strings.xml
index 1e4f779..2441f85 100644
--- a/packages/PackageInstaller/res/values-da/strings.xml
+++ b/packages/PackageInstaller/res/values-da/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Appen er installeret."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du opdatere denne app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Appen blev ikke installeret."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Pakken blev forhindret i at blive installeret."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Appen blev ikke installeret, da pakken er i strid med en eksisterende pakke."</string>
diff --git a/packages/PackageInstaller/res/values-de/strings.xml b/packages/PackageInstaller/res/values-de/strings.xml
index 2ce1b59..24cfc55 100644
--- a/packages/PackageInstaller/res/values-de/strings.xml
+++ b/packages/PackageInstaller/res/values-de/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"App wurde installiert."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Möchtest du diese App installieren?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Möchtest du diese App aktualisieren?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"App wurde nicht installiert."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Die Installation des Pakets wurde blockiert."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Die App wurde nicht installiert, da das Paket in Konflikt mit einem bestehenden Paket steht."</string>
diff --git a/packages/PackageInstaller/res/values-el/strings.xml b/packages/PackageInstaller/res/values-el/strings.xml
index df9bec2..ce8356b 100644
--- a/packages/PackageInstaller/res/values-el/strings.xml
+++ b/packages/PackageInstaller/res/values-el/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Η εφαρμογή εγκαταστάθηκε."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Θέλετε να εγκαταστήσετε αυτήν την εφαρμογή;"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Θέλετε να ενημερώσετε αυτήν την εφαρμογή;"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Η εφαρμογή δεν εγκαταστάθηκε."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Η εγκατάσταση του πακέτου αποκλείστηκε."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Η εφαρμογή δεν εγκαταστάθηκε, επειδή το πακέτο είναι σε διένεξη με κάποιο υπάρχον πακέτο."</string>
diff --git a/packages/PackageInstaller/res/values-en-rAU/strings.xml b/packages/PackageInstaller/res/values-en-rAU/strings.xml
index bd2d310..beec7c7 100644
--- a/packages/PackageInstaller/res/values-en-rAU/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rAU/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App installed."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rCA/strings.xml b/packages/PackageInstaller/res/values-en-rCA/strings.xml
index fa7cbdf..054506c 100644
--- a/packages/PackageInstaller/res/values-en-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rCA/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App installed."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rGB/strings.xml b/packages/PackageInstaller/res/values-en-rGB/strings.xml
index bd2d310..beec7c7 100644
--- a/packages/PackageInstaller/res/values-en-rGB/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rGB/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App installed."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rIN/strings.xml b/packages/PackageInstaller/res/values-en-rIN/strings.xml
index bd2d310..beec7c7 100644
--- a/packages/PackageInstaller/res/values-en-rIN/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rIN/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App installed."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-en-rXC/strings.xml b/packages/PackageInstaller/res/values-en-rXC/strings.xml
index 6ddb6e3..d8df532 100644
--- a/packages/PackageInstaller/res/values-en-rXC/strings.xml
+++ b/packages/PackageInstaller/res/values-en-rXC/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App installed."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Do you want to install this app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Do you want to update this app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> instead."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Updates to this app are currently managed by <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"App not installed."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"The package was blocked from being installed."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App not installed as package conflicts with an existing package."</string>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
index 97f3e87..b553986 100644
--- a/packages/PackageInstaller/res/values-es-rUS/strings.xml
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Se instaló la app."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"¿Deseas instalar esta app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"¿Deseas actualizar esta app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"No se instaló la app."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Se bloqueó el paquete para impedir la instalación."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"No se instaló la app debido a un conflicto con un paquete."</string>
diff --git a/packages/PackageInstaller/res/values-es/strings.xml b/packages/PackageInstaller/res/values-es/strings.xml
index 376e890..66e6bc3 100644
--- a/packages/PackageInstaller/res/values-es/strings.xml
+++ b/packages/PackageInstaller/res/values-es/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplicación instalada."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"¿Quieres instalar esta aplicación?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"¿Quieres actualizar esta aplicación?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"No se ha instalado la aplicación."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Se ha bloqueado la instalación del paquete."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"La aplicación no se ha instalado debido a un conflicto con un paquete."</string>
diff --git a/packages/PackageInstaller/res/values-et/strings.xml b/packages/PackageInstaller/res/values-et/strings.xml
index fbdcf0a..742f663 100644
--- a/packages/PackageInstaller/res/values-et/strings.xml
+++ b/packages/PackageInstaller/res/values-et/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Rakendus on installitud."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Kas soovite selle rakenduse installida?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Kas soovite seda rakendust värskendada?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Rakendus pole installitud."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketi installimine blokeeriti."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Rakendust ei installitud, kuna pakett on olemasoleva paketiga vastuolus."</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 9cf5de4..4687ab5 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Instalatu da aplikazioa."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Aplikazioa instalatu nahi duzu?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Aplikazioa eguneratu nahi duzu?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Ez da instalatu aplikazioa."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketea instalatzeko aukera blokeatu egin da."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Ez da instalatu aplikazioa, gatazka bat sortu delako lehendik dagoen pakete batekin."</string>
diff --git a/packages/PackageInstaller/res/values-fa/strings.xml b/packages/PackageInstaller/res/values-fa/strings.xml
index d4af663..dfe0873 100644
--- a/packages/PackageInstaller/res/values-fa/strings.xml
+++ b/packages/PackageInstaller/res/values-fa/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"برنامه نصب شد."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"میخواهید این برنامه را نصب کنید؟"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"میخواهید این برنامه را بهروزرسانی کنید؟"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"برنامه نصب نشد."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"از نصب شدن بسته جلوگیری شد."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"برنامه نصب نشد چون بسته با بسته موجود تداخل دارد."</string>
diff --git a/packages/PackageInstaller/res/values-fi/strings.xml b/packages/PackageInstaller/res/values-fi/strings.xml
index 98977cb..9a76c91 100644
--- a/packages/PackageInstaller/res/values-fi/strings.xml
+++ b/packages/PackageInstaller/res/values-fi/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Sovellus on asennettu."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Haluatko asentaa tämän sovelluksen?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Haluatko päivittää tämän sovelluksen?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Sovellusta ei asennettu."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketin asennus estettiin."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Sovellusta ei asennettu, koska paketti on ristiriidassa nykyisen paketin kanssa."</string>
diff --git a/packages/PackageInstaller/res/values-fr-rCA/strings.xml b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
index 0800ddf..9be6f5a 100644
--- a/packages/PackageInstaller/res/values-fr-rCA/strings.xml
+++ b/packages/PackageInstaller/res/values-fr-rCA/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Application installée."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette application?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette application?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du paquet a été bloquée."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le paquet entre en conflit avec un paquet existant."</string>
diff --git a/packages/PackageInstaller/res/values-fr/strings.xml b/packages/PackageInstaller/res/values-fr/strings.xml
index 58e3878..7744fabe 100644
--- a/packages/PackageInstaller/res/values-fr/strings.xml
+++ b/packages/PackageInstaller/res/values-fr/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Application installée."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Voulez-vous installer cette appli ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Voulez-vous mettre à jour cette appli ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Application non installée."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"L\'installation du package a été bloquée."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"L\'application n\'a pas été installée, car le package est en conflit avec un package déjà présent."</string>
diff --git a/packages/PackageInstaller/res/values-gl/strings.xml b/packages/PackageInstaller/res/values-gl/strings.xml
index 0ea985e..6ba8813 100644
--- a/packages/PackageInstaller/res/values-gl/strings.xml
+++ b/packages/PackageInstaller/res/values-gl/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Instalouse a aplicación."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Queres instalar esta aplicación?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Queres actualizar esta aplicación?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Non se instalou a aplicación"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Bloqueouse a instalación do paquete."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"A aplicación non se instalou porque o paquete presenta un conflito cun paquete que xa hai."</string>
diff --git a/packages/PackageInstaller/res/values-gu/strings.xml b/packages/PackageInstaller/res/values-gu/strings.xml
index 2c73875..d139b2b 100644
--- a/packages/PackageInstaller/res/values-gu/strings.xml
+++ b/packages/PackageInstaller/res/values-gu/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"શું તમે આ ઍપ ઇન્સ્ટૉલ કરવા માગો છો?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"શું તમે આ ઍપ અપડેટ કરવા માગો છો?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ઍપ્લિકેશન ઇન્સ્ટૉલ કરી નથી."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"પૅકેજને ઇન્સ્ટૉલ થવાથી બ્લૉક કરવામાં આવ્યું હતું."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"પૅકેજનો અસ્તિત્વમાંના પૅકેજ સાથે વિરોધાભાસ હોવાને કારણે ઍપ્લિકેશન ઇન્સ્ટૉલ થઈ નથી."</string>
diff --git a/packages/PackageInstaller/res/values-hi/strings.xml b/packages/PackageInstaller/res/values-hi/strings.xml
index 67b6b2f..17cf962 100644
--- a/packages/PackageInstaller/res/values-hi/strings.xml
+++ b/packages/PackageInstaller/res/values-hi/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ऐप्लिकेशन इंस्टॉल हो गया."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"क्या आपको यह ऐप्लिकेशन इंस्टॉल करना है?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"क्या आप इस ऐप्लिकेशन को अपडेट करना चाहते हैं?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ऐप्लिकेशन इंस्टॉल नहीं हुआ."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"पैकेज को इंस्टॉल होने से ब्लॉक किया हुआ है."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ऐप्लिकेशन इंस्टॉल नहीं हुआ क्योंकि पैकेज का किसी मौजूदा पैकेज से विरोध है."</string>
diff --git a/packages/PackageInstaller/res/values-hr/strings.xml b/packages/PackageInstaller/res/values-hr/strings.xml
index 02e8957..9b7eeea 100644
--- a/packages/PackageInstaller/res/values-hr/strings.xml
+++ b/packages/PackageInstaller/res/values-hr/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacija je instalirana."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Želite li instalirati ovu aplikaciju?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Želite li ažurirati ovu aplikaciju?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacija nije instalirana."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instaliranje paketa blokirano je."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija koja nije instalirana kao paket u sukobu je s postojećim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-hu/strings.xml b/packages/PackageInstaller/res/values-hu/strings.xml
index 8d48ceb..10e79a6 100644
--- a/packages/PackageInstaller/res/values-hu/strings.xml
+++ b/packages/PackageInstaller/res/values-hu/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Alkalmazás telepítve."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Telepíti ezt az alkalmazást?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Frissíti ezt az alkalmazást?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Az alkalmazás nincs telepítve."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"A csomag telepítését letiltotta a rendszer."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"A nem csomagként telepített alkalmazás ütközik egy már létező csomaggal."</string>
diff --git a/packages/PackageInstaller/res/values-hy/strings.xml b/packages/PackageInstaller/res/values-hy/strings.xml
index 881f397..0b46090 100644
--- a/packages/PackageInstaller/res/values-hy/strings.xml
+++ b/packages/PackageInstaller/res/values-hy/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Հավելվածը տեղադրված է:"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Տեղադրե՞լ այս հավելվածը:"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Թարմացնե՞լ այս հավելվածը։"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Հավելվածը տեղադրված չէ:"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Փաթեթի տեղադրումն արգելափակվել է:"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Հավելվածը չի տեղադրվել, քանի որ տեղադրման փաթեթն ունի հակասություն առկա փաթեթի հետ:"</string>
diff --git a/packages/PackageInstaller/res/values-in/strings.xml b/packages/PackageInstaller/res/values-in/strings.xml
index d20e134..ed25528 100644
--- a/packages/PackageInstaller/res/values-in/strings.xml
+++ b/packages/PackageInstaller/res/values-in/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikasi terinstal."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Ingin menginstal aplikasi ini?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Ingin mengupdate aplikasi ini?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak terinstal."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paket diblokir sehingga tidak dapat diinstal."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikasi tidak diinstal karena paket ini bentrok dengan paket yang sudah ada."</string>
diff --git a/packages/PackageInstaller/res/values-is/strings.xml b/packages/PackageInstaller/res/values-is/strings.xml
index 5132c6b..0c35415 100644
--- a/packages/PackageInstaller/res/values-is/strings.xml
+++ b/packages/PackageInstaller/res/values-is/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Forritið er uppsett."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Viltu setja upp þetta forrit?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Viltu uppfæra þetta forrit?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Forritið er ekki uppsett."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Lokað var á uppsetningu pakkans."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Forritið var ekki sett upp vegna árekstra á milli pakkans og annars pakka."</string>
diff --git a/packages/PackageInstaller/res/values-it/strings.xml b/packages/PackageInstaller/res/values-it/strings.xml
index ba7fd07..bfc1e03 100644
--- a/packages/PackageInstaller/res/values-it/strings.xml
+++ b/packages/PackageInstaller/res/values-it/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"App installata."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vuoi installare questa app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vuoi aggiornare questa app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"App non installata."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"È stata bloccata l\'installazione del pacchetto."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App non installata poiché il pacchetto è in conflitto con un pacchetto esistente."</string>
diff --git a/packages/PackageInstaller/res/values-iw/strings.xml b/packages/PackageInstaller/res/values-iw/strings.xml
index 141fd25..0cd7b30 100644
--- a/packages/PackageInstaller/res/values-iw/strings.xml
+++ b/packages/PackageInstaller/res/values-iw/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"האפליקציה הותקנה."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"האם ברצונך להתקין אפליקציה זו?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"האם ברצונך לעדכן אפליקציה זו?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"האפליקציה לא הותקנה."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"החבילה נחסמה להתקנה."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"האפליקציה לא הותקנה כי החבילה מתנגשת עם חבילה קיימת."</string>
diff --git a/packages/PackageInstaller/res/values-ja/strings.xml b/packages/PackageInstaller/res/values-ja/strings.xml
index af78e23..47e295a 100644
--- a/packages/PackageInstaller/res/values-ja/strings.xml
+++ b/packages/PackageInstaller/res/values-ja/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"アプリをインストールしました。"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"このアプリをインストールしますか?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"このアプリを更新しますか?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"アプリはインストールされていません。"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"パッケージのインストールはブロックされています。"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"パッケージが既存のパッケージと競合するため、アプリをインストールできませんでした。"</string>
diff --git a/packages/PackageInstaller/res/values-ka/strings.xml b/packages/PackageInstaller/res/values-ka/strings.xml
index ef822b6..56b79f6 100644
--- a/packages/PackageInstaller/res/values-ka/strings.xml
+++ b/packages/PackageInstaller/res/values-ka/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"აპი დაინსტალირებულია."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"გნებავთ ამ აპის დაყენება?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"გსურთ ამ აპის განახლება?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"აპი დაუინსტალირებელია."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ამ პაკეტის ინსტალაცია დაბლოკილია."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"აპი ვერ დაინსტალირდა, რადგან პაკეტი კონფლიქტშია არსებულ პაკეტთან."</string>
diff --git a/packages/PackageInstaller/res/values-kk/strings.xml b/packages/PackageInstaller/res/values-kk/strings.xml
index 267a8b1..d6ce0ce 100644
--- a/packages/PackageInstaller/res/values-kk/strings.xml
+++ b/packages/PackageInstaller/res/values-kk/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Қолданба орнатылды."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Бұл қолданбаны орнатқыңыз келе ме?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Бұл қолданбаны жаңартқыңыз келе ме?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Қолданба орнатылмады."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Пакетті орнатуға тыйым салынды."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Жаңа пакет пен бұрыннан бар пакеттің арасында қайшылық туындағандықтан, қолданба орнатылмады."</string>
diff --git a/packages/PackageInstaller/res/values-km/strings.xml b/packages/PackageInstaller/res/values-km/strings.xml
index e195289..7efe082 100644
--- a/packages/PackageInstaller/res/values-km/strings.xml
+++ b/packages/PackageInstaller/res/values-km/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"បានដំឡើងកម្មវិធី។"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"តើអ្នកចង់ដំឡើងកម្មវិធីនេះដែរទេ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"តើអ្នកចង់ដំឡើងកំណែកម្មវិធីនេះដែរទេ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"មិនបានដំឡើងកម្មវិធីទេ។"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"កញ្ចប់ត្រូវបានទប់ស្កាត់មិនឱ្យដំឡើង។"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"កម្មវិធីមិនបានដំឡើងទេ ដោយសារកញ្ចប់កម្មវិធីមិនត្រូវគ្នាជាមួយកញ្ចប់ដែលមានស្រាប់។"</string>
diff --git a/packages/PackageInstaller/res/values-kn/strings.xml b/packages/PackageInstaller/res/values-kn/strings.xml
index e74565c..57a9b64a 100644
--- a/packages/PackageInstaller/res/values-kn/strings.xml
+++ b/packages/PackageInstaller/res/values-kn/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ಆ್ಯಪ್ ಅನ್ನು ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಬಯಸುವಿರಾ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ಆ್ಯಪ್ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿಲ್ಲ."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡುವ ಪ್ಯಾಕೇಜ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ಪ್ಯಾಕೇಜ್ನಂತೆ ಇನ್ಸ್ಟಾಲ್ ಮಾಡಲಾಗಿರುವ ಆ್ಯಪ್ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಪ್ಯಾಕೇಜ್ ಜೊತೆಗೆ ಸಂಘರ್ಷವಾಗುತ್ತದೆ."</string>
diff --git a/packages/PackageInstaller/res/values-ko/strings.xml b/packages/PackageInstaller/res/values-ko/strings.xml
index 440017f..dbc7bc8 100644
--- a/packages/PackageInstaller/res/values-ko/strings.xml
+++ b/packages/PackageInstaller/res/values-ko/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"앱이 설치되었습니다."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"이 앱을 설치하시겠습니까?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"이 앱을 업데이트하시겠습니까?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"앱이 설치되지 않았습니다."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"패키지 설치가 차단되었습니다."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"패키지가 기존 패키지와 충돌하여 앱이 설치되지 않았습니다."</string>
diff --git a/packages/PackageInstaller/res/values-ky/strings.xml b/packages/PackageInstaller/res/values-ky/strings.xml
index be04f96..614fbaf 100644
--- a/packages/PackageInstaller/res/values-ky/strings.xml
+++ b/packages/PackageInstaller/res/values-ky/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Колдонмо орнотулду."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Бул колдонмону орнотоюн деп жатасызбы?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Бул колдонмону жаңыртайын деп жатасызбы?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Колдонмо орнотулган жок."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Топтомду орнотууга болбойт."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Башка топтом менен дал келбегендиктен колдонмо орнотулган жок."</string>
@@ -93,7 +97,7 @@
<string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Сыналгыңыз жана жеке дайын-даректериңиз белгисиз колдонмолордон зыян тартып калышы мүмкүн. Бул колдонмону орнотуп, аны пайдалануудан улам сыналгыңызга кандайдыр бир зыян келтирилсе же дайын-даректериңизды жоготуп алсаңыз, өзүңүз жооптуу болосуз."</string>
<string name="cloned_app_label" msgid="7503612829833756160">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> клону"</string>
<string name="anonymous_source_continue" msgid="4375745439457209366">"Улантуу"</string>
- <string name="external_sources_settings" msgid="4046964413071713807">"Жөндөөлөр"</string>
+ <string name="external_sources_settings" msgid="4046964413071713807">"Параметрлер"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"Тагынма колдонмолорду орнотуу/чыгаруу"</string>
<string name="app_installed_notification_channel_description" msgid="2695385797601574123">"Колдонмолорду орноткучтун билдирмелери"</string>
<string name="notification_installation_success_message" msgid="6450467996056038442">"Ийгиликтүү орнотулду"</string>
diff --git a/packages/PackageInstaller/res/values-lo/strings.xml b/packages/PackageInstaller/res/values-lo/strings.xml
index 4dd1134..d8779e7 100644
--- a/packages/PackageInstaller/res/values-lo/strings.xml
+++ b/packages/PackageInstaller/res/values-lo/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ຕິດຕັ້ງແອັບແລ້ວ."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ທ່ານຕ້ອງການຕິດຕັ້ງແອັບນີ້ບໍ່?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ທ່ານຕ້ອງການອັບເດດແອັບນີ້ບໍ່?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເທື່ອ."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ແພັກເກດຖືກບລັອກບໍ່ໃຫ້ໄດ້ຮັບການຕິດຕັ້ງ."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ບໍ່ໄດ້ຕິດຕັ້ງແອັບເນື່ອງຈາກແພັກເກດຂັດແຍ່ງກັບແພັກເກດທີ່ມີຢູ່ກ່ອນແລ້ວ."</string>
diff --git a/packages/PackageInstaller/res/values-lt/strings.xml b/packages/PackageInstaller/res/values-lt/strings.xml
index c92adeb..a58fc8e17 100644
--- a/packages/PackageInstaller/res/values-lt/strings.xml
+++ b/packages/PackageInstaller/res/values-lt/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"Programa įdiegta."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Ar norite įdiegti šią programą?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Ar norite atnaujinti šią programą?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Šios programos naujinius šiuo metu valdo <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAtnaujinę būsimus naujinius gausite iš <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Šios programos naujinius šiuo metu valdo <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAr norite įdiegti šį naujinį iš <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
<string name="install_failed" msgid="5777824004474125469">"Programa neįdiegta."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketas užblokuotas ir negali būti įdiegtas."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Programa neįdiegta, nes paketas nesuderinamas su esamu paketu."</string>
diff --git a/packages/PackageInstaller/res/values-lv/strings.xml b/packages/PackageInstaller/res/values-lv/strings.xml
index bff1100..8b011be 100644
--- a/packages/PackageInstaller/res/values-lv/strings.xml
+++ b/packages/PackageInstaller/res/values-lv/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Lietotne ir instalēta."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vai vēlaties instalēt šo lietotni?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vai vēlaties atjaunināt šo lietotni?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Lietotne nav instalēta."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Pakotnes instalēšana tika bloķēta."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Lietotne netika instalēta, jo pastāv pakotnes konflikts ar esošu pakotni."</string>
diff --git a/packages/PackageInstaller/res/values-mk/strings.xml b/packages/PackageInstaller/res/values-mk/strings.xml
index 4b35089..3c681e9 100644
--- a/packages/PackageInstaller/res/values-mk/strings.xml
+++ b/packages/PackageInstaller/res/values-mk/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Апликацијата е инсталирана."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Дали сакате да ја инсталирате апликацијава?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Дали сакате да ја ажурирате апликацијава?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Апликацијата не е инсталирана."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирањето на пакетот е блокирано."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Апликација што не е инсталирана како пакет е во конфликт со постоечки пакет."</string>
diff --git a/packages/PackageInstaller/res/values-ml/strings.xml b/packages/PackageInstaller/res/values-ml/strings.xml
index 0b57374..aa3aac0 100644
--- a/packages/PackageInstaller/res/values-ml/strings.xml
+++ b/packages/PackageInstaller/res/values-ml/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തു."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ഈ ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്യണോ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ഈ ആപ്പ് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"പാക്കേജ് ഇൻസ്റ്റാൾ ചെയ്യുന്നത് ബ്ലോക്ക് ചെയ്തു."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"പാക്കേജിന് നിലവിലുള്ള പാക്കേജുമായി പൊരുത്തക്കേടുള്ളതിനാൽ, ആപ്പ് ഇൻസ്റ്റാൾ ചെയ്തില്ല."</string>
diff --git a/packages/PackageInstaller/res/values-mn/strings.xml b/packages/PackageInstaller/res/values-mn/strings.xml
index 8d7dde0..112e2f1 100644
--- a/packages/PackageInstaller/res/values-mn/strings.xml
+++ b/packages/PackageInstaller/res/values-mn/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Аппыг суулгасан."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Та энэ аппыг суулгахыг хүсэж байна уу?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Та энэ аппыг шинэчлэхийг хүсэж байна уу?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Аппыг суулгаагүй."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Багц суулгахыг блоклосон байна."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Багц одоо байгаа багцтай тохирохгүй байгаа тул аппыг суулгаж чадсангүй."</string>
diff --git a/packages/PackageInstaller/res/values-mr/strings.xml b/packages/PackageInstaller/res/values-mr/strings.xml
index b0a7625..5a79715 100644
--- a/packages/PackageInstaller/res/values-mr/strings.xml
+++ b/packages/PackageInstaller/res/values-mr/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"अॅप इंस्टॉल झाले."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"तुम्हाला हे ॲप इंस्टॉल करायचे आहे का?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"तुम्हाला हे ॲप अपडेट करायचे आहे का?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"अॅप इंस्टॉल झाले नाही."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"पॅकेज इंस्टॉल होण्यापासून ब्लॉक केले होते."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"पॅकेजचा विद्यमान पॅकेजशी विरोध असल्याने अॅप इंस्टॉल झाले नाही."</string>
diff --git a/packages/PackageInstaller/res/values-ms/strings.xml b/packages/PackageInstaller/res/values-ms/strings.xml
index 4c8739d0..8d5e25f 100644
--- a/packages/PackageInstaller/res/values-ms/strings.xml
+++ b/packages/PackageInstaller/res/values-ms/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikasi dipasang."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Adakah anda ingin memasang aplikasi ini?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Adakah anda mahu mengemas kini apl ini?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikasi tidak dipasang."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Pakej ini telah disekat daripada dipasang."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Apl tidak dipasang kerana pakej bercanggah dengan pakej yang sedia ada."</string>
diff --git a/packages/PackageInstaller/res/values-my/strings.xml b/packages/PackageInstaller/res/values-my/strings.xml
index 077f4ee..a9ac033 100644
--- a/packages/PackageInstaller/res/values-my/strings.xml
+++ b/packages/PackageInstaller/res/values-my/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"အက်ပ်ထည့်သွင်းပြီးပါပြီ။"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ဤအက်ပ်ကို ထည့်သွင်းလိုသလား။"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ဤအက်ပ်ကို အပ်ဒိတ်လုပ်လိုသလား။"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"အက်ပ်မထည့်သွင်းရသေးပါ"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ပက်ကေ့ဂျ်ထည့်သွင်းခြင်းကို ပိတ်ထားသည်။"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ပက်ကေ့ဂျ်အဖြစ် ထည့်သွင်းမထားသော အက်ပ်သည် လက်ရှိပက်ကေ့ဂျ်နှင့် တိုက်နေသည်။"</string>
diff --git a/packages/PackageInstaller/res/values-nb/strings.xml b/packages/PackageInstaller/res/values-nb/strings.xml
index b144c5c..5f70b9d 100644
--- a/packages/PackageInstaller/res/values-nb/strings.xml
+++ b/packages/PackageInstaller/res/values-nb/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Appen er installert."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vil du installere denne appen?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vil du oppdatere denne appen?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Appen ble ikke installert."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Pakken er blokkert fra å bli installert."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Appen ble ikke installert fordi pakken er i konflikt med en eksisterende pakke."</string>
diff --git a/packages/PackageInstaller/res/values-ne/strings.xml b/packages/PackageInstaller/res/values-ne/strings.xml
index d0be534..e7e03a4 100644
--- a/packages/PackageInstaller/res/values-ne/strings.xml
+++ b/packages/PackageInstaller/res/values-ne/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"एप इन्स्टल गरियो।"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"तपाईं यो एप इन्स्टल गर्न चाहनुहुन्छ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"तपाईं यो एप अपडेट गर्न चाहनुहुन्छ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"एप स्थापना गरिएन।"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"यो प्याकेज स्थापना गर्ने क्रममा अवरोध गरियो।"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"प्याकेजका रूपमा स्थापना नगरिएको एप विद्यमान प्याकेजसँग मेल खाँदैन।"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index bc32d2f..a859861 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"App geïnstalleerd."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Wil je deze app installeren?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Wil je deze app updaten?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"App niet geïnstalleerd."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"De installatie van het pakket is geblokkeerd."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"App die niet is geïnstalleerd als pakket conflicteert met een bestaand pakket."</string>
diff --git a/packages/PackageInstaller/res/values-or/strings.xml b/packages/PackageInstaller/res/values-or/strings.xml
index 6858610..5131a11 100644
--- a/packages/PackageInstaller/res/values-or/strings.xml
+++ b/packages/PackageInstaller/res/values-or/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ଆପ ଇନଷ୍ଟଲ ହୋଇଗଲା।"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ଆପଣ ଏହି ଆପକୁ ଇନଷ୍ଟଲ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ଆପଣ ଏହି ଆପକୁ ଅପଡେଟ୍ କରିବା ପାଇଁ ଚାହୁଁଛନ୍ତି କି?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ଆପ୍ ଇନଷ୍ଟଲ୍ ହୋଇନାହିଁ।"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ଏହି ପ୍ୟାକେଜ୍କୁ ଇନଷ୍ଟଲ୍ କରାଯିବାରୁ ଅବରୋଧ କରାଯାଇଥିଲା।"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ପୂର୍ବରୁ ଥିବା ପ୍ୟାକେଜ୍ ସହ ଏହି ପ୍ୟାକେଜ୍ର ସମସ୍ୟା ଉପୁଯିବାରୁ ଆପ୍ ଇନଷ୍ଟଲ୍ ହୋଇପାରିଲା ନାହିଁ।"</string>
diff --git a/packages/PackageInstaller/res/values-pa/strings.xml b/packages/PackageInstaller/res/values-pa/strings.xml
index a670b7c..34373f9 100644
--- a/packages/PackageInstaller/res/values-pa/strings.xml
+++ b/packages/PackageInstaller/res/values-pa/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ਐਪ ਸਥਾਪਤ ਕੀਤੀ ਗਈ।"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ਕੀ ਤੁਸੀਂ ਇਸ ਐਪ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ਪੈਕੇਜ ਨੂੰ ਸਥਾਪਤ ਹੋਣ ਤੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਸੀ।"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ਪੈਕੇਜ ਦੇ ਇੱਕ ਮੌਜੂਦਾ ਪੈਕੇਜ ਨਾਲ ਵਿਵਾਦ ਹੋਣ ਕਰਕੇ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ।"</string>
diff --git a/packages/PackageInstaller/res/values-pl/strings.xml b/packages/PackageInstaller/res/values-pl/strings.xml
index 419008b..6626f39 100644
--- a/packages/PackageInstaller/res/values-pl/strings.xml
+++ b/packages/PackageInstaller/res/values-pl/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacja została zainstalowana."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Zainstalować tę aplikację?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Zaktualizować tę aplikację?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacja nie została zainstalowana."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instalacja pakietu została zablokowana."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacja nie została zainstalowana, bo powoduje konflikt z istniejącym pakietem."</string>
diff --git a/packages/PackageInstaller/res/values-pt-rBR/strings.xml b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
index dfc04bb..51f94e2 100644
--- a/packages/PackageInstaller/res/values-pt-rBR/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rBR/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"App instalado."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index ae497ce..07bd2de 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"App instalada."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Instalar esta app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Pretende atualizar esta app?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Atualmente, as atualizações desta app são geridas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nAo atualizar, vai obter atualizações futuras de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Atualmente, as atualizações desta app são geridas por <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g>.\n\nQuer instalar esta atualização de <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g>?"</string>
<string name="install_failed" msgid="5777824004474125469">"Aplicação não instalada."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Foi bloqueada a instalação do pacote."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"A app não foi instalada porque o pacote entra em conflito com um pacote existente."</string>
diff --git a/packages/PackageInstaller/res/values-pt/strings.xml b/packages/PackageInstaller/res/values-pt/strings.xml
index dfc04bb..51f94e2 100644
--- a/packages/PackageInstaller/res/values-pt/strings.xml
+++ b/packages/PackageInstaller/res/values-pt/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"App instalado."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Quer instalar esse app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Quer atualizar esse app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"O app não foi instalado."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"A instalação do pacote foi bloqueada."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Como o pacote tem um conflito com um pacote já existente, o app não foi instalado."</string>
diff --git a/packages/PackageInstaller/res/values-ro/strings.xml b/packages/PackageInstaller/res/values-ro/strings.xml
index e529804..0de0ac0 100644
--- a/packages/PackageInstaller/res/values-ro/strings.xml
+++ b/packages/PackageInstaller/res/values-ro/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplicație instalată."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vrei să instalezi această aplicație?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vrei să actualizezi această aplicație?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplicația nu a fost instalată."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instalarea pachetului a fost blocată."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplicația nu a fost instalată deoarece pachetul intră în conflict cu un pachet existent."</string>
diff --git a/packages/PackageInstaller/res/values-ru/strings.xml b/packages/PackageInstaller/res/values-ru/strings.xml
index 0d5b855..106d325 100644
--- a/packages/PackageInstaller/res/values-ru/strings.xml
+++ b/packages/PackageInstaller/res/values-ru/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Приложение установлено."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Установить приложение?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Обновить приложение?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Приложение не установлено."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Установка пакета заблокирована."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Приложение не установлено, так как оно конфликтует с другим пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-si/strings.xml b/packages/PackageInstaller/res/values-si/strings.xml
index 8dc1b83..e2880eb 100644
--- a/packages/PackageInstaller/res/values-si/strings.xml
+++ b/packages/PackageInstaller/res/values-si/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"යෙදුම ස්ථාපනය කර ඇත."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"මෙම යෙදුම ස්ථාපනය කිරීමට ඔබට අවශ්යද?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"ඔබට මෙම යෙදුම යාවත්කාලීන කිරීමට අවශ්යද?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"යෙදුම ස්ථාපනය කර නැත."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"මෙම පැකේජය ස්ථාපනය කිරීම අවහිර කරන ලදි."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"පැකේජය දැනට පවතින පැකේජයක් සමග ගැටෙන නිසා යෙදුම ස්ථාපනය නොකරන ලදී."</string>
diff --git a/packages/PackageInstaller/res/values-sk/strings.xml b/packages/PackageInstaller/res/values-sk/strings.xml
index 48d5cdd..b5ecf78 100644
--- a/packages/PackageInstaller/res/values-sk/strings.xml
+++ b/packages/PackageInstaller/res/values-sk/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikácia bola nainštalovaná."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Chcete túto aplikáciu nainštalovať?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Chcete túto aplikáciu aktualizovať?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikácia nebola nainštalovaná."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Inštalácia balíka bola zablokovaná."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikácia sa nenainštalovala, pretože balík je v konflikte s existujúcim balíkom."</string>
diff --git a/packages/PackageInstaller/res/values-sl/strings.xml b/packages/PackageInstaller/res/values-sl/strings.xml
index 392e589..fe4e717 100644
--- a/packages/PackageInstaller/res/values-sl/strings.xml
+++ b/packages/PackageInstaller/res/values-sl/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacija je nameščena."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Ali želite namestiti to aplikacijo?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Ali želite posodobiti to aplikacijo?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacija ni nameščena."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Namestitev paketa je bila blokirana."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacija ni bila nameščena, ker je paket v navzkrižju z obstoječim paketom."</string>
diff --git a/packages/PackageInstaller/res/values-sq/strings.xml b/packages/PackageInstaller/res/values-sq/strings.xml
index 853677f..b52bccd 100644
--- a/packages/PackageInstaller/res/values-sq/strings.xml
+++ b/packages/PackageInstaller/res/values-sq/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Aplikacioni u instalua."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Dëshiron ta instalosh këtë aplikacion?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Dëshiron ta përditësosh këtë aplikacion?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Aplikacioni nuk u instalua."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Instalimi paketës u bllokua."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Aplikacioni nuk u instalua pasi paketa është në konflikt me një paketë ekzistuese."</string>
diff --git a/packages/PackageInstaller/res/values-sr/strings.xml b/packages/PackageInstaller/res/values-sr/strings.xml
index a38fccf..19c77ce 100644
--- a/packages/PackageInstaller/res/values-sr/strings.xml
+++ b/packages/PackageInstaller/res/values-sr/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Апликација је инсталирана."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Желите да инсталирате ову апликацију?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Желите да ажурирате ову апликацију?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Апликација није инсталирана."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Инсталирање пакета је блокирано."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Апликација није инсталирана јер је пакет неусаглашен са постојећим пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-sv/strings.xml b/packages/PackageInstaller/res/values-sv/strings.xml
index ab2f65e..351e3f8 100644
--- a/packages/PackageInstaller/res/values-sv/strings.xml
+++ b/packages/PackageInstaller/res/values-sv/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Appen har installerats."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Vill du installera den här appen?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Vill du uppdatera den här appen?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Appen har inte installerats."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketet har blockerats för installation."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Appen har inte installerats på grund av en konflikt mellan detta paket och ett befintligt paket."</string>
diff --git a/packages/PackageInstaller/res/values-sw/strings.xml b/packages/PackageInstaller/res/values-sw/strings.xml
index 5f1126a..b7ffc29 100644
--- a/packages/PackageInstaller/res/values-sw/strings.xml
+++ b/packages/PackageInstaller/res/values-sw/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Imesakinisha programu."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Ungependa kusakinisha programu hii?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Ungependa kusasisha programu hii?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Imeshindwa kusakinisha programu."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Kifurushi kimezuiwa kisisakinishwe."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Programu haikusakinishwa kwa sababu kifurushi kinakinzana na kifurushi kingine kilichopo."</string>
diff --git a/packages/PackageInstaller/res/values-ta/strings.xml b/packages/PackageInstaller/res/values-ta/strings.xml
index 8b31d6d..ad0c9a0 100644
--- a/packages/PackageInstaller/res/values-ta/strings.xml
+++ b/packages/PackageInstaller/res/values-ta/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ஆப்ஸ் நிறுவப்பட்டது."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"இந்த ஆப்ஸை நிறுவ வேண்டுமா?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"இந்த ஆப்ஸைப் புதுப்பிக்க வேண்டுமா?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ஆப்ஸ் நிறுவப்படவில்லை."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"இந்தத் தொகுப்பு நிறுவப்படுவதிலிருந்து தடுக்கப்பட்டது."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"இந்தத் தொகுப்பு ஏற்கனவே உள்ள தொகுப்புடன் முரண்படுவதால் ஆப்ஸ் நிறுவப்படவில்லை."</string>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index c9b7d52..6ab13dc 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"యాప్ ఇన్స్టాల్ చేయబడింది."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"మీరు ఈ యాప్ను ఇన్స్టాల్ చేయాలనుకుంటున్నారా?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"మీరు ఈ యాప్ను అప్డేట్ చేయాలనుకుంటున్నారా?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"యాప్ ఇన్స్టాల్ చేయబడలేదు."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"ప్యాకేజీ ఇన్స్టాల్ కాకుండా బ్లాక్ చేయబడింది."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ప్యాకేజీ, అలాగే ఇప్పటికే ఉన్న ప్యాకేజీ మధ్య వైరుధ్యం ఉన్నందున యాప్ ఇన్స్టాల్ చేయబడలేదు."</string>
diff --git a/packages/PackageInstaller/res/values-th/strings.xml b/packages/PackageInstaller/res/values-th/strings.xml
index b865a7c..0e7274b 100644
--- a/packages/PackageInstaller/res/values-th/strings.xml
+++ b/packages/PackageInstaller/res/values-th/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"ติดตั้งแอปแล้ว"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"คุณต้องการติดตั้งแอปนี้ไหม"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"คุณต้องการอัปเดตแอปนี้ไหม"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"ไม่ได้ติดตั้งแอป"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"มีการบล็อกแพ็กเกจไม่ให้ติดตั้ง"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ไม่ได้ติดตั้งแอปเพราะแพ็กเกจขัดแย้งกับแพ็กเกจที่มีอยู่"</string>
diff --git a/packages/PackageInstaller/res/values-tl/strings.xml b/packages/PackageInstaller/res/values-tl/strings.xml
index 8fafc6d..5f480bc 100644
--- a/packages/PackageInstaller/res/values-tl/strings.xml
+++ b/packages/PackageInstaller/res/values-tl/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Na-install na ang app."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Gusto mo bang i-install ang app na ito?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Gusto mo bang i-update ang app na ito?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Hindi na-install ang app."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Na-block ang pag-install sa package."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Hindi na-install ang app dahil nagkakaproblema ang package sa isang dati nang package."</string>
diff --git a/packages/PackageInstaller/res/values-tr/strings.xml b/packages/PackageInstaller/res/values-tr/strings.xml
index 217c40e..7eacad0 100644
--- a/packages/PackageInstaller/res/values-tr/strings.xml
+++ b/packages/PackageInstaller/res/values-tr/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Uygulama yüklendi."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Bu uygulamayı yüklemek istiyor musunuz?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Bu uygulamayı güncellemek istiyor musunuz?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Uygulama yüklenmedi."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paketin yüklemesi engellendi."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Paket, mevcut bir paketle çakıştığından uygulama yüklenemedi."</string>
diff --git a/packages/PackageInstaller/res/values-uk/strings.xml b/packages/PackageInstaller/res/values-uk/strings.xml
index f0695f7..e94c716 100644
--- a/packages/PackageInstaller/res/values-uk/strings.xml
+++ b/packages/PackageInstaller/res/values-uk/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Програму встановлено."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Установити цей додаток?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Оновити цей додаток?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Програму не встановлено."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Встановлення пакета заблоковано."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Додаток не встановлено, оскільки пакет конфліктує з наявним пакетом."</string>
diff --git a/packages/PackageInstaller/res/values-ur/strings.xml b/packages/PackageInstaller/res/values-ur/strings.xml
index 34a1230..1327d48 100644
--- a/packages/PackageInstaller/res/values-ur/strings.xml
+++ b/packages/PackageInstaller/res/values-ur/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"ایپ انسٹال ہو گئی۔"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"کیا آپ یہ ایپ انسٹال کرنا چاہتے ہیں؟"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"کیا آپ یہ ایپ اپ ڈیٹ کرنا چاہتے ہیں؟"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"اس ایپس میں اپ ڈیٹس <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> کے زیر انتظام ہیں۔\n\nاپ ڈیٹ کر کے، آپ اس کے بجائے <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> سے مستقبل کی اپ ڈیٹس موصول کر سکتے ہیں۔"</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"اس ایپس میں اپ ڈیٹس <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> کے زیر انتظام ہیں۔\n\nآپ یہ اپ ڈیٹ <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> سے انسٹال کرنا چاہتے ہیں۔"</string>
<string name="install_failed" msgid="5777824004474125469">"ایپ انسٹال نہیں ہوئی۔"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"پیکج کو انسٹال ہونے سے مسدود کر دیا گیا تھا۔"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"ایپ انسٹال نہیں ہوئی کیونکہ پیکج ایک موجودہ پیکیج سے متصادم ہے۔"</string>
diff --git a/packages/PackageInstaller/res/values-uz/strings.xml b/packages/PackageInstaller/res/values-uz/strings.xml
index 945fb92..ef8f6b3 100644
--- a/packages/PackageInstaller/res/values-uz/strings.xml
+++ b/packages/PackageInstaller/res/values-uz/strings.xml
@@ -26,6 +26,8 @@
<string name="install_done" msgid="5987363587661783896">"Ilova o‘rnatildi."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Bu ilovani oʻrnatmoqchimisiz?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Bu ilova yangilansinmi?"</string>
+ <string name="install_confirm_question_update_owner_changed" msgid="4215696609006069124">"Bu ilova yangilanishlari hozirda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> boshqaruvida.\n\nYangilanishida kelgusi oʻzgarishlar <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> dan keladi."</string>
+ <string name="install_confirm_question_update_owner_reminder" msgid="8778026710268011466">"Bu ilova yangilanishlari hozirda <xliff:g id="EXISTING_UPDATE_OWNER">%1$s</xliff:g> boshqaruvida.\n\nBu yangilanish <xliff:g id="NEW_UPDATE_OWNER">%2$s</xliff:g> dan oʻrnatilsinmi?"</string>
<string name="install_failed" msgid="5777824004474125469">"Ilova o‘rnatilmadi."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Paket o‘rnatilishga qarshi bloklangan."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Paket mavjud paket bilan zid kelganligi uchun ilovani o‘rnatib bo‘lmadi."</string>
diff --git a/packages/PackageInstaller/res/values-vi/strings.xml b/packages/PackageInstaller/res/values-vi/strings.xml
index fd65a79..234cd2a 100644
--- a/packages/PackageInstaller/res/values-vi/strings.xml
+++ b/packages/PackageInstaller/res/values-vi/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Ứng dụng đã được cài đặt."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Bạn có muốn cài đặt ứng dụng này không?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Bạn có muốn cập nhật ứng dụng này không?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Ứng dụng chưa được cài đặt."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Đã chặn cài đặt gói."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Chưa cài đặt được ứng dụng do gói xung đột với một gói hiện có."</string>
diff --git a/packages/PackageInstaller/res/values-zh-rCN/strings.xml b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
index 0ba356a..737bf23 100644
--- a/packages/PackageInstaller/res/values-zh-rCN/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rCN/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"已安装应用。"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"要安装此应用吗?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此应用吗?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"未安装应用。"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"系统已禁止安装该软件包。"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"应用未安装:软件包与现有软件包存在冲突。"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rHK/strings.xml b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
index 9f08fb8..0ed0bd7 100644
--- a/packages/PackageInstaller/res/values-zh-rHK/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rHK/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"要安裝此應用程式嗎?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"要更新此應用程式嗎?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"套件已遭封鎖,無法安裝。"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"套件與現有的套件發生衝突,無法安裝應用程式。"</string>
diff --git a/packages/PackageInstaller/res/values-zh-rTW/strings.xml b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
index f9121c1..9dfb3fd 100644
--- a/packages/PackageInstaller/res/values-zh-rTW/strings.xml
+++ b/packages/PackageInstaller/res/values-zh-rTW/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"已安裝應用程式。"</string>
<string name="install_confirm_question" msgid="7663733664476363311">"要安裝這個應用程式嗎?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"要更新這個應用程式嗎?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"未安裝應用程式。"</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"系統已封鎖這個套件,因此無法安裝。"</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"應用程式套件與現有套件衝突,因此未能完成安裝。"</string>
diff --git a/packages/PackageInstaller/res/values-zu/strings.xml b/packages/PackageInstaller/res/values-zu/strings.xml
index a88a042..f5e6b75 100644
--- a/packages/PackageInstaller/res/values-zu/strings.xml
+++ b/packages/PackageInstaller/res/values-zu/strings.xml
@@ -26,6 +26,10 @@
<string name="install_done" msgid="5987363587661783896">"Uhlelo lokusebenza olufakiwe."</string>
<string name="install_confirm_question" msgid="7663733664476363311">"Ingabe ufuna ukufaka le app?"</string>
<string name="install_confirm_question_update" msgid="3348888852318388584">"Ingabe ufuna ukubuyekeza le app?"</string>
+ <!-- no translation found for install_confirm_question_update_owner_changed (4215696609006069124) -->
+ <skip />
+ <!-- no translation found for install_confirm_question_update_owner_reminder (8778026710268011466) -->
+ <skip />
<string name="install_failed" msgid="5777824004474125469">"Uhlelo lokusebenza alufakiwe."</string>
<string name="install_failed_blocked" msgid="8512284352994752094">"Iphakheji livinjiwe kusukela ekufakweni."</string>
<string name="install_failed_conflict" msgid="3493184212162521426">"Uhlelo lokusebenza alufakiwe njengoba ukuphakheja kushayisana nephakheji elikhona."</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
index 21f4be0..1bbdad5 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -275,8 +275,11 @@
}
/**
- * Returns whether there is only one user on this device, not including
- * the system-only user.
+ * Returns whether there is only one "full" user on this device.
+ *
+ * <p><b>Note:</b> on devices that use {@link android.os.UserManager#isHeadlessSystemUserMode()
+ * headless system user mode}, the system user is not "full", so it's not be considered in the
+ * calculation.
*/
private boolean isSingleUser(UserManager userManager) {
final int userCount = userManager.getUserCount();
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
index 5c5720a..cc2e3a6 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
@@ -128,8 +128,7 @@
}
/**
- * Returns whether there is only one user on this device, not including
- * the system-only user.
+ * Returns whether there is only one user on this device.
*/
private boolean isSingleUser(UserManager userManager) {
final int userCount = userManager.getUserCount();
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
index f4a893a..bcd6784b 100644
--- a/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/res/values-ky/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="settings_label" msgid="5948970810295631236">"Жөндөөлөр"</string>
+ <string name="settings_label" msgid="5948970810295631236">"Параметрлер"</string>
</resources>
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/NavControllerWrapper.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/NavControllerWrapper.kt
index eb2bffe..1aa2079 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/NavControllerWrapper.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/NavControllerWrapper.kt
@@ -25,7 +25,7 @@
import androidx.navigation.NavHostController
interface NavControllerWrapper {
- fun navigate(route: String)
+ fun navigate(route: String, popUpCurrent: Boolean = false)
fun navigateBack()
val highlightEntryId: String?
@@ -48,17 +48,17 @@
val LocalNavController = compositionLocalOf<NavControllerWrapper> {
object : NavControllerWrapper {
- override fun navigate(route: String) {}
+ override fun navigate(route: String, popUpCurrent: Boolean) {}
override fun navigateBack() {}
}
}
@Composable
-fun navigator(route: String?): () -> Unit {
+fun navigator(route: String?, popUpCurrent: Boolean = false): () -> Unit {
if (route == null) return {}
val navController = LocalNavController.current
- return { navController.navigate(route) }
+ return { navController.navigate(route, popUpCurrent) }
}
internal class NavControllerWrapperImpl(
@@ -68,8 +68,16 @@
var highlightId: String? = null
var sessionName: String? = null
- override fun navigate(route: String) {
- navController.navigate(route)
+ override fun navigate(route: String, popUpCurrent: Boolean) {
+ navController.navigate(route) {
+ if (popUpCurrent) {
+ navController.currentDestination?.let { currentDestination ->
+ popUpTo(currentDestination.id) {
+ inclusive = true
+ }
+ }
+ }
+ }
}
override fun navigateBack() {
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/AnnotatedStringResource.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/AnnotatedStringResource.kt
new file mode 100644
index 0000000..9ddd0c6
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/AnnotatedStringResource.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.settingslib.spa.framework.util
+
+import android.content.res.Resources
+import android.graphics.Typeface
+import android.text.Spanned
+import android.text.style.StyleSpan
+import android.text.style.URLSpan
+import androidx.annotation.StringRes
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Density
+
+const val URLSPAN_TAG = "URLSPAN_TAG"
+
+@Composable
+fun annotatedStringResource(@StringRes id: Int, urlSpanColor: Color): AnnotatedString {
+ LocalConfiguration.current
+ val resources = LocalContext.current.resources
+ val density = LocalDensity.current
+ return remember(id) {
+ val text = resources.getText(id)
+ spannableStringToAnnotatedString(text, density, urlSpanColor)
+ }
+}
+
+private fun spannableStringToAnnotatedString(text: CharSequence, density: Density, urlSpanColor: Color): AnnotatedString {
+ return if (text is Spanned) {
+ with(density) {
+ buildAnnotatedString {
+ append((text.toString()))
+ text.getSpans(0, text.length, Any::class.java).forEach {
+ val start = text.getSpanStart(it)
+ val end = text.getSpanEnd(it)
+ when (it) {
+ is StyleSpan ->
+ when (it.style) {
+ Typeface.NORMAL -> addStyle(
+ SpanStyle(
+ fontWeight = FontWeight.Normal,
+ fontStyle = FontStyle.Normal
+ ),
+ start,
+ end
+ )
+ Typeface.BOLD -> addStyle(
+ SpanStyle(
+ fontWeight = FontWeight.Bold,
+ fontStyle = FontStyle.Normal
+ ),
+ start,
+ end
+ )
+ Typeface.ITALIC -> addStyle(
+ SpanStyle(
+ fontWeight = FontWeight.Normal,
+ fontStyle = FontStyle.Italic
+ ),
+ start,
+ end
+ )
+ Typeface.BOLD_ITALIC -> addStyle(
+ SpanStyle(
+ fontWeight = FontWeight.Bold,
+ fontStyle = FontStyle.Italic
+ ),
+ start,
+ end
+ )
+ }
+ is URLSpan -> {
+ addStyle(
+ SpanStyle(
+ color = urlSpanColor,
+ ),
+ start,
+ end
+ )
+ if (!it.url.isNullOrEmpty()) {
+ addStringAnnotation(
+ URLSPAN_TAG,
+ it.url,
+ start,
+ end
+ )
+ }
+ }
+ else -> addStyle(SpanStyle(), start, end)
+ }
+ }
+ }
+ }
+ } else {
+ AnnotatedString(text.toString())
+ }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Footer.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Footer.kt
index 296cf3b..d9d3b37 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Footer.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Footer.kt
@@ -34,15 +34,22 @@
@Composable
fun Footer(footerText: String) {
if (footerText.isEmpty()) return
+ Footer {
+ SettingsBody(footerText)
+ }
+}
+
+@Composable
+fun Footer(content: @Composable () -> Unit) {
Column(Modifier.padding(SettingsDimension.itemPadding)) {
Icon(
- imageVector = Icons.Outlined.Info,
- contentDescription = null,
- modifier = Modifier.size(SettingsDimension.itemIconSize),
- tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ imageVector = Icons.Outlined.Info,
+ contentDescription = null,
+ modifier = Modifier.size(SettingsDimension.itemIconSize),
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
Spacer(modifier = Modifier.height(SettingsDimension.itemPaddingVertical))
- SettingsBody(footerText)
+ content()
}
}
diff --git a/packages/SettingsLib/Spa/tests/res/values/strings.xml b/packages/SettingsLib/Spa/tests/res/values/strings.xml
index 1ca425c..cbfea06 100644
--- a/packages/SettingsLib/Spa/tests/res/values/strings.xml
+++ b/packages/SettingsLib/Spa/tests/res/values/strings.xml
@@ -25,4 +25,6 @@
=1 {There is one song found in {place}.}
other {There are # songs found in {place}.}
}</string>
+
+ <string name="test_annotated_string_resource">Annotated string with <b>bold</b> and <a href="https://www.google.com/">link</a>.</string>
</resources>
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/NavControllerWrapperTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/NavControllerWrapperTest.kt
new file mode 100644
index 0000000..118585e
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/compose/NavControllerWrapperTest.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.settingslib.spa.framework.compose
+
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.waitUntilExists
+import kotlinx.coroutines.delay
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NavControllerWrapperTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun navigate_canNavigate() {
+ composeTestRule.setContent {
+ TestNavHost {
+ LocalNavController.current.navigate(ROUTE_B)
+ }
+ }
+
+ composeTestRule.onNodeWithText(ROUTE_B).assertIsDisplayed()
+ }
+
+ @Test
+ fun navigate_canNavigateBack() {
+ composeTestRule.setContent {
+ TestNavHost {
+ val navController = LocalNavController.current
+ LaunchedEffect(Unit) {
+ navController.navigate(ROUTE_B)
+ delay(100)
+ navController.navigateBack()
+ }
+ }
+ }
+
+ composeTestRule.waitUntilExists(hasText(ROUTE_A))
+ }
+
+ @Test
+ fun navigate_canNavigateAndPopUpCurrent() {
+ composeTestRule.setContent {
+ TestNavHost {
+ val navController = LocalNavController.current
+ LaunchedEffect(Unit) {
+ navController.navigate(ROUTE_B)
+ delay(100)
+ navController.navigate(ROUTE_C, popUpCurrent = true)
+ delay(100)
+ navController.navigateBack()
+ }
+ }
+ }
+
+ composeTestRule.waitUntilExists(hasText(ROUTE_A))
+ }
+
+ private companion object {
+ @Composable
+ fun TestNavHost(content: @Composable () -> Unit) {
+ val navController = rememberNavController()
+ CompositionLocalProvider(navController.localNavController()) {
+ NavHost(navController, ROUTE_A) {
+ composable(route = ROUTE_A) { Text(ROUTE_A) }
+ composable(route = ROUTE_B) { Text(ROUTE_B) }
+ composable(route = ROUTE_C) { Text(ROUTE_C) }
+ }
+ content()
+ }
+ }
+
+ const val ROUTE_A = "RouteA"
+ const val ROUTE_B = "RouteB"
+ const val ROUTE_C = "RouteC"
+ }
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/AnnotatedStringResourceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/AnnotatedStringResourceTest.kt
new file mode 100644
index 0000000..b65be42
--- /dev/null
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/AnnotatedStringResourceTest.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.settingslib.spa.framework.util
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.util.URLSPAN_TAG
+import com.android.settingslib.spa.framework.util.annotatedStringResource
+import com.android.settingslib.spa.test.R
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class AnnotatedStringResourceTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ @Test
+ fun testAnnotatedStringResource() {
+ composeTestRule.setContent {
+ val annotatedString = annotatedStringResource(R.string.test_annotated_string_resource, Color.Blue)
+
+ val annotations = annotatedString.getStringAnnotations(0, annotatedString.length)
+ assertThat(annotations).hasSize(1)
+ assertThat(annotations[0].start).isEqualTo(31)
+ assertThat(annotations[0].end).isEqualTo(35)
+ assertThat(annotations[0].tag).isEqualTo(URLSPAN_TAG)
+ assertThat(annotations[0].item).isEqualTo("https://www.google.com/")
+
+ assertThat(annotatedString.spanStyles).hasSize(2)
+ assertThat(annotatedString.spanStyles[0].start).isEqualTo(22)
+ assertThat(annotatedString.spanStyles[0].end).isEqualTo(26)
+ assertThat(annotatedString.spanStyles[0].item).isEqualTo(
+ SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Normal))
+
+ assertThat(annotatedString.spanStyles[1].start).isEqualTo(31)
+ assertThat(annotatedString.spanStyles[1].end).isEqualTo(35)
+ assertThat(annotatedString.spanStyles[1].item).isEqualTo(SpanStyle(color = Color.Blue))
+ }
+ }
+}
diff --git a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FakeNavControllerWrapper.kt b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FakeNavControllerWrapper.kt
index 5a3044d..f289d0d 100644
--- a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FakeNavControllerWrapper.kt
+++ b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FakeNavControllerWrapper.kt
@@ -25,7 +25,7 @@
var navigateCalledWith: String? = null
var navigateBackIsCalled = false
- override fun navigate(route: String) {
+ override fun navigate(route: String, popUpCurrent: Boolean) {
navigateCalledWith = route
}
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml
index 3ad7bb0..b5a70d0 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-af/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Toegelaat"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nie toegelaat nie"</string>
<string name="version_text" msgid="4001669804596458577">"weergawe <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml
index 4c2525bfd..3cc6e89 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-am/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ይፈቀዳል"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"አይፈቀድም"</string>
<string name="version_text" msgid="4001669804596458577">"ሥሪት <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
index 436914d..2e0a9ef 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ar/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"مسموح به"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غير مسموح به"</string>
<string name="version_text" msgid="4001669804596458577">"الإصدار <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml
index c1c88f2..dd27aa1 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-as/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"অনুমতি দিয়া হৈছে"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"অনুমতি নাই"</string>
<string name="version_text" msgid="4001669804596458577">"সংস্কৰণ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml
index 4fc090a..1fc9c36 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-az/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"İcazə verildi"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"İcazə verilməyib"</string>
<string name="version_text" msgid="4001669804596458577">"versiya <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml
index 3708503..3d5caaf 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-b+sr+Latn/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozvoljeno"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dozvoljeno"</string>
<string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml
index 38fb12b..f3c3dd0 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-be/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дазволена"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Забаронена"</string>
<string name="version_text" msgid="4001669804596458577">"версія <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml
index b9b03bf..c16bea8 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bg/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Разрешено"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Не е разрешено"</string>
<string name="version_text" msgid="4001669804596458577">"версия <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml
index b805b3c..a72570f 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bn/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"অনুমোদিত"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"অননুমোদিত"</string>
<string name="version_text" msgid="4001669804596458577">"ভার্সন <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml
index 9ceb340..9b98057 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-bs/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozvoljeno"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dozvoljeno"</string>
<string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml
index 00cb41b..111abe3 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ca/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Amb permís"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Sense permís"</string>
<string name="version_text" msgid="4001669804596458577">"versió <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml
index 7b28f11..f58e9c4 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-cs/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Povoleno"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepovoleno"</string>
<string name="version_text" msgid="4001669804596458577">"verze <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml
index f1893be..32ae008 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-da/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tilladt"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ikke tilladt"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml
index 471a7a7..401d8c9 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-de/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Zulässig"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nicht zulässig"</string>
<string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml
index 6c46e27..ad751f5 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-el/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Επιτρέπεται"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Δεν επιτρέπεται"</string>
<string name="version_text" msgid="4001669804596458577">"έκδοση <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml
index de48ff1..b151c95 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rAU/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
<string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rCA/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rCA/strings.xml
index bc88528..523813d 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rCA/strings.xml
@@ -23,4 +23,5 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <string name="cloned_app_info_label" msgid="1765651167024478391">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone"</string>
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml
index de48ff1..b151c95 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rGB/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
<string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml
index de48ff1..b151c95 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rIN/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
<string name="version_text" msgid="4001669804596458577">"Version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-en-rXC/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-en-rXC/strings.xml
index c395286..6f9ffe1 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-en-rXC/strings.xml
@@ -23,4 +23,5 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Allowed"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Not allowed"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <string name="cloned_app_info_label" msgid="1765651167024478391">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> clone"</string>
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml
index d211eeb..b08a73f 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-es-rUS/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"No se permite"</string>
<string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml
index d907cb8..45da42c 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-es/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"No permitida"</string>
<string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml
index 2be2967..d8f43d8 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-et/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Lubatud"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Pole lubatud"</string>
<string name="version_text" msgid="4001669804596458577">"versioon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml
index 7fb2ee28..6505096 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-eu/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Baimena dauka"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ez dauka baimenik"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> bertsioa"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
index 7711cac..616cf87 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fa/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"مجاز"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"غیرمجاز"</string>
<string name="version_text" msgid="4001669804596458577">"نسخه <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml
index af65bfe..161f2ae 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fi/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Sallittu"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ei sallittu"</string>
<string name="version_text" msgid="4001669804596458577">"versio <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml
index 31f1ee0..5fd70cc 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fr-rCA/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Autorisé"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non autorisée"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml
index 5b7b5e6..239a86a 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-fr/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Autorisé"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non autorisé"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml
index 3d1f9d8..809d24d 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-gl/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non permitida"</string>
<string name="version_text" msgid="4001669804596458577">"versión <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml
index c598b70..a1de2fb 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-gu/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"મંજૂરી છે"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"મંજૂરી નથી"</string>
<string name="version_text" msgid="4001669804596458577">"વર્ઝન <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml
index 809afd3..9af4a02 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hi/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति है"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नहीं है"</string>
<string name="version_text" msgid="4001669804596458577">"वर्शन <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml
index 1a87974..8556cfb 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hr/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dopušteno"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nije dopušteno"</string>
<string name="version_text" msgid="4001669804596458577">"verzija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml
index 1ae7cdf..9d928e9 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hu/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Engedélyezve"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nem engedélyezett"</string>
<string name="version_text" msgid="4001669804596458577">"verzió: <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml
index 353af77..064d9998 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-hy/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Թույլատրված է"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Արգելված է"</string>
<string name="version_text" msgid="4001669804596458577">"տարբերակ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
index 8b766b0..8799c9b 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-in/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Diizinkan"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tidak diizinkan"</string>
<string name="version_text" msgid="4001669804596458577">"versi <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml
index cbd412d..ff7ee6a 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-is/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Leyft"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ekki leyft"</string>
<string name="version_text" msgid="4001669804596458577">"útgáfa <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml
index d83c70d..5d67307 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-it/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Consentita"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Non consentita"</string>
<string name="version_text" msgid="4001669804596458577">"versione <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml
index 7ed8a6b..4ab76fe 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-iw/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"יש הרשאה"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"אין הרשאה"</string>
<string name="version_text" msgid="4001669804596458577">"גרסה <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml
index b12cb5c..1c0d8d3 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ja/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"許可"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"許可しない"</string>
<string name="version_text" msgid="4001669804596458577">"バージョン <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml
index c01a028..a4c6783 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ka/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"დაშვებულია"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"დაუშვებელია"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> ვერსია"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml
index fb94404..4760d47 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-kk/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Рұқсат етілген"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Рұқсат етілмеген"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> нұсқасы"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml
index 610123d..962fb5c 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-km/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"បានអនុញ្ញាត"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"មិនអនុញ្ញាតទេ"</string>
<string name="version_text" msgid="4001669804596458577">"កំណែ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml
index b61c008..7edec75 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-kn/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ಅನುಮತಿಸಲಾಗಿದೆ"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
<string name="version_text" msgid="4001669804596458577">"ಆವೃತ್ತಿ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml
index 660dc0e..446580b 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ko/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"허용됨"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"허용되지 않음"</string>
<string name="version_text" msgid="4001669804596458577">"버전 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml
index 898ec09..2596b93 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ky/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Уруксат берилген"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Тыюу салынган"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> версиясы"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml
index d0f77e4..0dc64a6 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lo/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ອະນຸຍາດແລ້ວ"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ບໍ່ໄດ້ອະນຸຍາດ"</string>
<string name="version_text" msgid="4001669804596458577">"ເວີຊັນ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml
index 7d33f91..4ca01dc 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lt/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Leidžiama"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Neleidžiama"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> versija"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml
index 66dc44d..bf300ac 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-lv/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Atļauja piešķirta"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Atļauja nav piešķirta"</string>
<string name="version_text" msgid="4001669804596458577">"versija <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml
index db55600..839e4c7 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mk/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Со дозволен пристап"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Без дозволен пристап"</string>
<string name="version_text" msgid="4001669804596458577">"верзија <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml
index c99d0d3..0aad964 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ml/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"അനുവാദം ലഭിച്ചു"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"അനുവാദം ലഭിച്ചില്ല"</string>
<string name="version_text" msgid="4001669804596458577">"പതിപ്പ് <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml
index bc0864b..bc6e9ae 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mn/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Зөвшөөрсөн"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Зөвшөөрөөгүй"</string>
<string name="version_text" msgid="4001669804596458577">"хувилбар <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml
index 55a178b..142a60f 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-mr/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमती असलेले"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमती नाही"</string>
<string name="version_text" msgid="4001669804596458577">"आवृत्ती <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml
index a736de9..0d39435 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ms/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dibenarkan"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tidak dibenarkan"</string>
<string name="version_text" msgid="4001669804596458577">"versi <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml
index 3bed608..f87608f 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-my/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ခွင့်ပြုထားသည်"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ခွင့်ပြုမထားပါ"</string>
<string name="version_text" msgid="4001669804596458577">"ဗားရှင်း <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml
index d6bd063..745834d 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-nb/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tillatt"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ikke tillatt"</string>
<string name="version_text" msgid="4001669804596458577">"versjon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
index 97db4ea..4b99bae1 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ne/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"अनुमति दिइएका एप"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"अनुमति नदिइएका एप"</string>
<string name="version_text" msgid="4001669804596458577">"संस्करण <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml
index 7157e3f..9a6b767 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-nl/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Toegestaan"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Niet toegestaan"</string>
<string name="version_text" msgid="4001669804596458577">"versie <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml
index 24779e3..e562d55 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-or/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ଅନୁମତି ଦିଆଯାଇଛି"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ଅନୁମତି ଦିଆଯାଇନାହିଁ"</string>
<string name="version_text" msgid="4001669804596458577">"ଭର୍ସନ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml
index fe1a3eb..a24ec90 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pa/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ਆਗਿਆ ਹੈ"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ਆਗਿਆ ਨਹੀਂ ਹੈ"</string>
<string name="version_text" msgid="4001669804596458577">"ਵਰਜਨ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml
index 9d5ba9d..7da29a5 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pl/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dozwolone"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Niedozwolone"</string>
<string name="version_text" msgid="4001669804596458577">"wersja <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml
index 18a31d8..85a42e2 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt-rBR/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitido"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitido"</string>
<string name="version_text" msgid="4001669804596458577">"Versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml
index ddf5e51..9db985d 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt-rPT/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitida"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitida"</string>
<string name="version_text" msgid="4001669804596458577">"versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml
index 18a31d8..85a42e2 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-pt/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permitido"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Não permitido"</string>
<string name="version_text" msgid="4001669804596458577">"Versão <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml
index ef58fb8..e808e4a 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ro/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Permisă"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepermisă"</string>
<string name="version_text" msgid="4001669804596458577">"versiunea <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml
index 6d69c80..404ed31 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ru/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Разрешено"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Запрещено"</string>
<string name="version_text" msgid="4001669804596458577">"версия <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml
index d2c20e6..276cbc4 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-si/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"ඉඩ දුන්"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ඉඩ නොදෙන"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> අනුවාදය"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml
index 0d0984f..d8dde40 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sk/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Povolené"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nepovolené"</string>
<string name="version_text" msgid="4001669804596458577">"verzia <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml
index c8bd15a..4cb2a40 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sl/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Dovoljeno"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ni dovoljeno"</string>
<string name="version_text" msgid="4001669804596458577">"različica <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml
index 112868a..ba3d3cb 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sq/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Lejohet"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Nuk lejohet"</string>
<string name="version_text" msgid="4001669804596458577">"versioni <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml
index 4c99d60..75caa5a 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sr/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дозвољено"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Није дозвољено"</string>
<string name="version_text" msgid="4001669804596458577">"верзија <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml
index 1dd5efd..e11bb12 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sv/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Tillåts"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Tillåts inte"</string>
<string name="version_text" msgid="4001669804596458577">"version <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml
index a0ee70c..be04d8e 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-sw/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Inaruhusiwa"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Hairuhusiwi"</string>
<string name="version_text" msgid="4001669804596458577">"toleo la <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml
index 36d64e8..cab94e2 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ta/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"அனுமதிக்கப்பட்டது"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"அனுமதிக்கப்படவில்லை"</string>
<string name="version_text" msgid="4001669804596458577">"பதிப்பு <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml
index a908dd4..721e86a 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-te/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"అనుమతించబడినవి"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"అనుమతించబడలేదు"</string>
<string name="version_text" msgid="4001669804596458577">"వెర్షన్ <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml
index 1d7db1a..0844e24 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-th/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"อนุญาต"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"ไม่อนุญาต"</string>
<string name="version_text" msgid="4001669804596458577">"เวอร์ชัน <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml
index fb56559a..1d0bead 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-tl/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Pinapahintulutan"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Hindi pinapahintulutan"</string>
<string name="version_text" msgid="4001669804596458577">"bersyon <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml
index 5f5722b..e3fcf4d 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-tr/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"İzin veriliyor"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"İzin verilmiyor"</string>
<string name="version_text" msgid="4001669804596458577">"sürüm: <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml
index a8632ca..392738c 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-uk/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Дозволено"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Заборонено"</string>
<string name="version_text" msgid="4001669804596458577">"версія <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml
index 4b969bb..c05c387 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-ur/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"اجازت ہے"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"اجازت نہیں ہے"</string>
<string name="version_text" msgid="4001669804596458577">"ورژن <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml
index aed34e6..2c7f827 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-uz/strings.xml
@@ -23,4 +23,5 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Ruxsat berilgan"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Ruxsat berilmagan"</string>
<string name="version_text" msgid="4001669804596458577">"<xliff:g id="VERSION_NUM">%1$s</xliff:g> versiya"</string>
+ <string name="cloned_app_info_label" msgid="1765651167024478391">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> nusxasi"</string>
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml
index 75700c7..dbef24b 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-vi/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Được phép"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Không được phép"</string>
<string name="version_text" msgid="4001669804596458577">"phiên bản <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml
index 2c864cb..fbd6fc7 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rCN/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"已允许"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允许"</string>
<string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml
index 667a10a..c05e560 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rHK/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"允許"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允許"</string>
<string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml
index 667a10a..c05e560 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zh-rTW/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"允許"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"不允許"</string>
<string name="version_text" msgid="4001669804596458577">"版本 <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml b/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml
index d3a614a..45d11cc 100644
--- a/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml
+++ b/packages/SettingsLib/SpaPrivileged/res/values-zu/strings.xml
@@ -23,4 +23,6 @@
<string name="app_permission_summary_allowed" msgid="6115213465364138103">"Kuvumelekile"</string>
<string name="app_permission_summary_not_allowed" msgid="58396132188553920">"Akuvumelekile"</string>
<string name="version_text" msgid="4001669804596458577">"Uhlobo <xliff:g id="VERSION_NUM">%1$s</xliff:g>"</string>
+ <!-- no translation found for cloned_app_info_label (1765651167024478391) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt
index 0b45da6..21c9e34 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfoPage.kt
@@ -29,6 +29,7 @@
packageName: String,
userId: Int,
footerText: String,
+ footerContent: (@Composable () -> Unit)?,
packageManagers: IPackageManagers,
content: @Composable PackageInfo.() -> Unit,
) {
@@ -40,6 +41,10 @@
packageInfo.content()
- Footer(footerText)
+ if (footerContent != null) {
+ Footer(footerContent)
+ } else {
+ Footer(footerText)
+ }
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
index 7199e3a..57a60e5 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
@@ -49,6 +49,7 @@
import com.android.settingslib.spaprivileged.model.app.AppListViewModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IAppListViewModel
+import com.android.settingslib.spaprivileged.model.app.userId
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@@ -135,7 +136,7 @@
header()
}
- items(count = list.size, key = { option to list[it].record.app.packageName }) {
+ items(count = list.size, key = { list[it].record.itemKey(option) }) {
remember(list) { getGroupTitleIfFirst(option, list, it) }
?.let { group -> CategoryTitle(title = group) }
@@ -149,6 +150,9 @@
}
}
+private fun <T : AppRecord> T.itemKey(option: Int) =
+ listOf(option, app.packageName, app.userId, System.identityHashCode(this))
+
/** Returns group title if this is the first item of the group. */
private fun <T : AppRecord> AppListModel<T>.getGroupTitleIfFirst(
option: Int,
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index e9fcbd2..7c689c6 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -141,6 +141,7 @@
packageName = packageName,
userId = userId,
footerText = stringResource(footerResId),
+ footerContent = footerContent(),
packageManagers = packageManagers,
) {
val model = createSwitchModel(applicationInfo)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index 1ab6230..f4b3204 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -20,6 +20,7 @@
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
+import androidx.compose.ui.text.AnnotatedString
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.rememberContext
@@ -36,7 +37,10 @@
val footerResId: Int
val switchRestrictionKeys: List<String>
get() = emptyList()
-
+ @Composable
+ fun footerContent(): (@Composable () -> Unit)? {
+ return null
+ }
/**
* Loads the extra info for the App List, and generates the [AppRecord] List.
*
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 66aaa56b..b69fd53 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -247,7 +247,7 @@
</string-array>
<string-array name="track_frame_time_entries">
<item msgid="634406443901014984">"關閉"</item>
- <item msgid="1288760936356000927">"在螢幕上以列顯示"</item>
+ <item msgid="1288760936356000927">"在螢幕上顯示長條圖"</item>
<item msgid="5023908510820531131">"在「<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>」指令中"</item>
</string-array>
<string-array name="debug_hw_overdraw_entries">
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 81c2a00..24bf57e 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -341,7 +341,7 @@
<string name="debug_app_set" msgid="6599535090477753651">"偵錯應用程式:<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="2543228890535466325">"選取應用程式"</string>
<string name="no_application" msgid="9038334538870247690">"無"</string>
- <string name="wait_for_debugger" msgid="7461199843335409809">"等待偵錯程式"</string>
+ <string name="wait_for_debugger" msgid="7461199843335409809">"等待偵錯工具"</string>
<string name="wait_for_debugger_summary" msgid="6846330006113363286">"執行受偵錯的應用程式之前,先等待偵錯程序附加完成"</string>
<string name="debug_input_category" msgid="7349460906970849771">"輸入"</string>
<string name="debug_drawing_category" msgid="5066171112313666619">"繪圖"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
index b73e7a3..d708e57 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -30,6 +30,7 @@
import static android.media.MediaRoute2Info.TYPE_USB_HEADSET;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+import static android.media.RouteListingPreference.Item.DISABLE_REASON_NONE;
import static android.media.RouteListingPreference.Item.FLAG_SUGGESTED_ROUTE;
import static com.android.settingslib.media.LocalMediaManager.MediaDeviceState.STATE_SELECTED;
@@ -193,6 +194,27 @@
public abstract String getId();
/**
+ * Get disabled reason of device
+ *
+ * @return disabled reason of device
+ */
+ @RouteListingPreference.Item.DisableReason
+ public int getDisableReason() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null
+ ? mItem.getDisableReason() : -1;
+ }
+
+ /**
+ * Checks if device is has disabled reason
+ *
+ * @return true if device has disabled reason
+ */
+ public boolean hasDisabledReason() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && mItem != null
+ && mItem.getDisableReason() != DISABLE_REASON_NONE;
+ }
+
+ /**
* Checks if device is suggested device from application
*
* @return true if device is suggested device
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index ae06193..c0818a8 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -39,7 +39,7 @@
*/
public static final String[] SETTINGS_TO_BACKUP = {
Settings.Global.APPLY_RAMPING_RINGER,
- Settings.Global.BUGREPORT_IN_POWER_MENU,
+ Settings.Global.BUGREPORT_IN_POWER_MENU, // moved to secure
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
Settings.Global.AUTO_TIME,
@@ -70,8 +70,8 @@
Settings.Global.ZEN_DURATION,
Settings.Global.CHARGING_VIBRATION_ENABLED,
Settings.Global.AWARE_ALLOWED,
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_APP,
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER,
+ Settings.Global.CUSTOM_BUGREPORT_HANDLER_APP, // moved to secure
+ Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER, // moved to secure
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Settings.Global.USER_DISABLED_HDR_FORMATS,
Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 06c3476..c133097 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -29,7 +29,7 @@
*/
@UnsupportedAppUsage
public static final String[] SETTINGS_TO_BACKUP = {
- Settings.Secure.BUGREPORT_IN_POWER_MENU, // moved to global
+ Settings.Secure.BUGREPORT_IN_POWER_MENU,
Settings.Secure.ALLOW_MOCK_LOCATION,
Settings.Secure.USB_MASS_STORAGE_ENABLED, // moved to global
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
@@ -225,6 +225,8 @@
Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED,
Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO,
Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE,
- Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME
+ Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME,
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_APP,
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index a1a9e8c..7b8ca4d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -306,6 +306,13 @@
VALIDATORS.put(Global.Wearable.COMPANION_OS_VERSION, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Global.Wearable.ENABLE_ALL_LANGUAGES, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.OEM_SETUP_VERSION, ANY_INTEGER_VALIDATOR);
+ VALIDATORS.put(
+ Global.Wearable.OEM_SETUP_COMPLETED_STATUS,
+ new DiscreteValueValidator(
+ new String[] {
+ String.valueOf(Global.Wearable.OEM_SETUP_COMPLETED_FAILURE),
+ String.valueOf(Global.Wearable.OEM_SETUP_COMPLETED_SUCCESS),
+ }));
VALIDATORS.put(Global.Wearable.MASTER_GESTURES_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.UNGAZE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index d72d4d5..03921e1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -357,5 +357,7 @@
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_CODE, ANY_STRING_VALIDATOR);
VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, ANY_STRING_VALIDATOR);
+ VALIDATORS.put(Secure.CUSTOM_BUGREPORT_HANDLER_APP, ANY_STRING_VALIDATOR);
+ VALIDATORS.put(Secure.CUSTOM_BUGREPORT_HANDLER_USER, ANY_INTEGER_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 8d4a35d..ede69be 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -363,9 +363,6 @@
Settings.Global.BOOT_COUNT,
GlobalSettingsProto.BOOT_COUNT);
dumpSetting(s, p,
- Settings.Global.BUGREPORT_IN_POWER_MENU,
- GlobalSettingsProto.BUGREPORT_IN_POWER_MENU);
- dumpSetting(s, p,
Settings.Global.CACHED_APPS_FREEZER_ENABLED,
GlobalSettingsProto.CACHED_APPS_FREEZER_ENABLED);
dumpSetting(s, p,
@@ -1629,6 +1626,7 @@
// Settings.Global.INSTALL_NON_MARKET_APPS intentionally excluded since it's deprecated.
// Settings.Global.APPLY_RAMPING_RINGER intentionally excluded since it's deprecated.
+ // Settings.Global.BUGREPORT_IN_POWER_MENU intentionally excluded since it's deprecated.
}
private static void dumpProtoConfigSettingsLocked(
@@ -1840,6 +1838,10 @@
Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS,
SecureSettingsProto.ALLOWED_GEOLOCATION_ORIGINS);
+ dumpSetting(s, p,
+ Settings.Secure.BUGREPORT_IN_POWER_MENU,
+ SecureSettingsProto.BUGREPORT_IN_POWER_MENU);
+
final long aovToken = p.start(SecureSettingsProto.ALWAYS_ON_VPN);
dumpSetting(s, p,
Settings.Secure.ALWAYS_ON_VPN_APP,
@@ -2662,7 +2664,6 @@
p.end(token);
// Settings.Secure.DEVELOPMENT_SETTINGS_ENABLED intentionally excluded since it's deprecated.
- // Settings.Secure.BUGREPORT_IN_POWER_MENU intentionally excluded since it's deprecated.
// Settings.Secure.ADB_ENABLED intentionally excluded since it's deprecated.
// Settings.Secure.ALLOW_MOCK_LOCATION intentionally excluded since it's deprecated.
// Settings.Secure.DATA_ROAMING intentionally excluded since it's deprecated.
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1356e1d..f740326 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3681,7 +3681,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 212;
+ private static final int SETTINGS_VERSION = 213;
private final int mUserId;
@@ -3791,6 +3791,7 @@
* currentVersion = 119;
* }
*/
+ @GuardedBy("mLock")
private int onUpgradeLocked(int userId, int oldVersion, int newVersion) {
if (DEBUG) {
Slog.w(LOG_TAG, "Upgrading settings for user: " + userId + " from version: "
@@ -5588,6 +5589,32 @@
currentVersion = 212;
}
+ if (currentVersion == 212) {
+ final SettingsState globalSettings = getGlobalSettingsLocked();
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+ final Setting bugReportInPowerMenu = globalSettings.getSettingLocked(
+ Global.BUGREPORT_IN_POWER_MENU);
+
+ if (!bugReportInPowerMenu.isNull()) {
+ Slog.i(LOG_TAG, "Setting bugreport_in_power_menu to "
+ + bugReportInPowerMenu.getValue() + " in Secure settings.");
+ secureSettings.insertSettingLocked(
+ Secure.BUGREPORT_IN_POWER_MENU,
+ bugReportInPowerMenu.getValue(), null /* tag */,
+ false /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME);
+
+ // set global bug_report_in_power_menu setting to null since it's deprecated
+ Slog.i(LOG_TAG, "Setting bugreport_in_power_menu to null"
+ + " in Global settings since it's deprecated.");
+ globalSettings.insertSettingLocked(
+ Global.BUGREPORT_IN_POWER_MENU, null /* value */, null /* tag */,
+ true /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ currentVersion = 213;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 5ee36f3..db7032e 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -645,6 +645,7 @@
Settings.Global.Wearable.ENABLE_ALL_LANGUAGES,
Settings.Global.Wearable.SETUP_LOCALE,
Settings.Global.Wearable.OEM_SETUP_VERSION,
+ Settings.Global.Wearable.OEM_SETUP_COMPLETED_STATUS,
Settings.Global.Wearable.MASTER_GESTURES_ENABLED,
Settings.Global.Wearable.UNGAZE_ENABLED,
Settings.Global.Wearable.BURN_IN_PROTECTION_ENABLED,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index c641a85..b4598bf 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -646,6 +646,9 @@
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+ <!-- Permission required for CTS test - SoundDoseHelperTest -->
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SYSTEM_SETTINGS" />
+
<!-- Permission required for CTS test - CtsAmbientContextDetectionServiceDeviceTest -->
<uses-permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 115cf792..628fb38 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -679,6 +679,20 @@
android:excludeFromRecents="true"
android:exported="true" />
+ <!-- started from Telecomm(CallsManager) -->
+ <activity
+ android:name=".telephony.ui.activity.SwitchToManagedProfileForCallActivity"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:finishOnCloseSystemDialogs="true"
+ android:permission="android.permission.MODIFY_PHONE_STATE"
+ android:theme="@style/Theme.SystemUI.Dialog.Alert">
+ <intent-filter>
+ <action android:name="android.telecom.action.SHOW_SWITCH_TO_WORK_PROFILE_FOR_CALL_DIALOG" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<!-- platform logo easter egg activity -->
<activity
android:name=".DessertCase"
@@ -923,7 +937,7 @@
android:excludeFromRecents="true"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/note_task_button_label"
- android:icon="@drawable/ic_note_task_button">
+ android:icon="@drawable/ic_note_task_shortcut_widget">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index ee8d023..2910bba 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -5,46 +5,72 @@
SystemUI is a persistent process that provides UI for the system but outside
of the system_server process.
-The starting point for most of sysui code is a list of services that extend
-SystemUI that are started up by SystemUIApplication. These services then depend
-on some custom dependency injection provided by Dependency.
-
Inputs directed at sysui (as opposed to general listeners) generally come in
through IStatusBar. Outputs from sysui are through a variety of private APIs to
the android platform all over.
## SystemUIApplication
-When SystemUIApplication starts up, it will start up the services listed in
-config_systemUIServiceComponents or config_systemUIServiceComponentsPerUser.
+When SystemUIApplication starts up, it instantiates a Dagger graph from which
+various pieces of the application are built.
-Each of these services extend SystemUI. SystemUI provides them with a Context
-and gives them callbacks for onConfigurationChanged (this historically was
-the main path for onConfigurationChanged, now also happens through
-ConfigurationController). They also receive a callback for onBootCompleted
+To support customization, SystemUIApplication relies on the AndroidManifest.xml
+having an `android.app.AppComponentFactory` specified. Specifically, it relies
+on an `AppComponentFactory` that subclases `SystemUIAppComponentFactoryBase`.
+Implementations of this abstract base class must override
+`#createSystemUIInitializer(Context)` which returns a `SystemUIInitializer`.
+`SystemUIInitializer` primary job in turn is to intialize and return the Dagger
+root component back to the `SystemUIApplication`.
+
+Writing a custom `SystemUIAppComponentFactoryBase` and `SystemUIInitializer`,
+should be enough for most implementations to stand up a customized Dagger
+graph, and launch a custom version of SystemUI.
+
+## Dagger / Dependency Injection
+
+See [dagger.md](docs/dagger.md) and https://dagger.dev/.
+
+## CoreStartable
+
+The starting point for most of SystemUI code is a list of classes that
+implement `CoreStartable` that are started up by SystemUIApplication.
+CoreStartables are like miniature services. They have their `#start` method
+called after being instantiated, and a reference to them is stored inside
+SystemUIApplication. They are in charge of their own behavior beyond this,
+registering and unregistering with the rest of the system as needed.
+
+`CoreStartable` also receives a callback for `#onBootCompleted`
since these objects may be started before the device has finished booting.
-Each SystemUI service is expected to be a major part of system ui and the
-goal is to minimize communication between them. So in general they should be
-relatively silo'd.
+`CoreStartable` is an ideal place to add new features and functionality
+that does not belong directly under the umbrella of an existing feature.
+It is better to define a new `CoreStartable` than to stick unrelated
+initialization code together in catch-all methods.
-## Dependencies
+CoreStartables are tied to application startup via Dagger:
-The first SystemUI service that is started should always be Dependency.
-Dependency provides a static method for getting a hold of dependencies that
-have a lifecycle that spans sysui. Dependency has code for how to create all
-dependencies manually added. SystemUIFactory is also capable of
-adding/replacing these dependencies.
+```kotlin
+class FeatureStartable
+@Inject
+constructor(
+ /* ... */
+) : CoreStartable {
+ override fun start() {
+ // ...
+ }
+}
-Dependencies are lazily initialized, so if a Dependency is never referenced at
-runtime, it will never be created.
+@Module
+abstract class FeatureModule {
+ @Binds
+ @IntoMap
+ @ClassKey(FeatureStartable::class)
+ abstract fun bind(impl: FeatureStartable): CoreStartable
+}
+```
-If an instantiated dependency implements Dumpable it will be included in dumps
-of sysui (and bug reports), allowing it to include current state information.
-This is how \*Controllers dump state to bug reports.
-
-If an instantiated dependency implements ConfigurationChangeReceiver it will
-receive onConfigurationChange callbacks when the configuration changes.
+Including `FeatureModule` in the Dagger graph such as this will ensure that
+`FeatureStartable` gets constructed and that its `#start` method is called.
## IStatusBar
@@ -64,12 +90,6 @@
This is generally used a shortcut to directly trigger CommandQueue rather than
calling StatusManager and waiting for the call to come back to IStatusBar.
-## Default SystemUI services list
-
-### [com.android.systemui.Dependency](/packages/SystemUI/src/com/android/systemui/Dependency.java)
-
-Provides custom dependency injection.
-
### [com.android.systemui.util.NotificationChannels](/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java)
Creates/initializes the channels sysui uses when posting notifications.
@@ -88,11 +108,11 @@
Registers all the callbacks/listeners required to show the Volume dialog when
it should be shown.
-### [com.android.systemui.status.phone.StatusBar](/packages/SystemUI/src/com/android/systemui/status/phone/StatusBar.java)
+### [com.android.systemui.status.phone.CentralSurfaces](/packages/SystemUI/src/com/android/systemui/status/phone/CentralSurfaces.java)
This shows the UI for the status bar and the notification shade it contains.
It also contains a significant amount of other UI that interacts with these
-surfaces (keyguard, AOD, etc.). StatusBar also contains a notification listener
+surfaces (keyguard, AOD, etc.). CentralSurfaces also contains a notification listener
to receive notification callbacks.
### [com.android.systemui.usb.StorageNotification](/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java)
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index f92625b..333aeba 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -16,6 +16,9 @@
},
{
"exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
}
]
}
@@ -73,16 +76,16 @@
// Curious where your @Scenario tests will run?
//
// @Ignore: nowhere
- // @Staging or @FlakyTest: in staged-postsubmit, but not postsubmit or
- // presubmit
+ // @FlakyTest: in staged-postsubmit, but not blocking postsubmit or
+ // presubmit
// @Postsubmit: in postsubmit and staged-postsubmit, but not presubmit
// none of the above: in presubmit, postsubmit, and staged-postsubmit
//
- // Therefore, please annotate new tests with @Staging, then with @Postsubmit
- // once they're ready for postsubmit, then with neither once they're ready
- // for presubmit.
+ // Ideally, please annotate new tests with @FlakyTest, then with @Postsubmit
+ // once they're ready for postsubmit as they will immediately block go/android-platinum,
+ // then with neither once they're ready for presubmit.
//
- // If you don't use @Staging or @Postsubmit, your new test will immediately
+ // If you don't use @Postsubmit, your new test will immediately
// block presubmit, which is probably not what you want!
"sysui-platinum-postsubmit": [
{
@@ -99,6 +102,9 @@
},
{
"exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
}
]
}
@@ -131,6 +137,9 @@
},
{
"include-filter": "android.platform.test.scenario.sysui"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.FlakyTest"
}
]
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
index 5c4fdcc..76139c6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/AccessibilityMenuService.java
@@ -16,7 +16,19 @@
package com.android.systemui.accessibility.accessibilitymenu;
+import android.accessibilityservice.AccessibilityButtonController;
import android.accessibilityservice.AccessibilityService;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.view.Display;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -24,32 +36,162 @@
import com.android.systemui.accessibility.accessibilitymenu.view.A11yMenuOverlayLayout;
/** @hide */
-public class AccessibilityMenuService extends AccessibilityService implements View.OnTouchListener {
+public class AccessibilityMenuService extends AccessibilityService
+ implements View.OnTouchListener {
private static final String TAG = "A11yMenuService";
+ private static final long BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE = 100L;
+
+ private long mLastTimeTouchedOutside = 0L;
+ // Timeout used to ignore the A11y button onClick() when ACTION_OUTSIDE is also received on
+ // clicking on the A11y button.
+ public static final long BUTTON_CLICK_TIMEOUT = 200;
+
private A11yMenuOverlayLayout mA11yMenuLayout;
+ private static boolean sInitialized = false;
+
+ // TODO(b/136716947): Support multi-display once a11y framework side is ready.
+ private DisplayManager mDisplayManager;
+ final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
+ int mRotation;
+
+ @Override
+ public void onDisplayAdded(int displayId) {}
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ // TODO(b/136716947): Need to reset A11yMenuOverlayLayout by display id.
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ if (mRotation != display.getRotation()) {
+ mRotation = display.getRotation();
+ mA11yMenuLayout.updateViewLayout();
+ }
+ }
+ };
+
+ // Update layout.
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+ private final Runnable mOnConfigChangedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (!sInitialized) {
+ return;
+ }
+ // Re-assign theme to service after onConfigurationChanged
+ getTheme().applyStyle(R.style.ServiceTheme, true);
+ // Caches & updates the page index to ViewPager when a11y menu is refreshed.
+ // Otherwise, the menu page would reset on a UI update.
+ int cachedPageIndex = mA11yMenuLayout.getPageIndex();
+ mA11yMenuLayout.configureLayout(cachedPageIndex);
+ }
+ };
+
@Override
public void onCreate() {
super.onCreate();
+
+ getAccessibilityButtonController().registerAccessibilityButtonCallback(
+ new AccessibilityButtonController.AccessibilityButtonCallback() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onClicked(AccessibilityButtonController controller) {
+ if (SystemClock.uptimeMillis() - mLastTimeTouchedOutside
+ > BUTTON_CLICK_TIMEOUT) {
+ mA11yMenuLayout.toggleVisibility();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAvailabilityChanged(AccessibilityButtonController controller,
+ boolean available) {}
+ }
+ );
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mHandler.hasCallbacks(mOnConfigChangedRunnable)) {
+ mHandler.removeCallbacks(mOnConfigChangedRunnable);
+ }
+
+ super.onDestroy();
}
@Override
protected void onServiceConnected() {
mA11yMenuLayout = new A11yMenuOverlayLayout(this);
- super.onServiceConnected();
- mA11yMenuLayout.toggleVisibility();
+
+ registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mA11yMenuLayout.hideMenu();
+ }}, new IntentFilter(Intent.ACTION_SCREEN_OFF)
+ );
+
+ mDisplayManager = getSystemService(DisplayManager.class);
+ mDisplayManager.registerDisplayListener(mDisplayListener, null);
+
+ sInitialized = true;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {}
+ /**
+ * This method would notify service when device configuration, such as display size,
+ * localization, orientation or theme, is changed.
+ *
+ * @param newConfig the new device configuration.
+ */
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ // Prevent update layout failure
+ // if multiple onConfigurationChanged are called at the same time.
+ if (mHandler.hasCallbacks(mOnConfigChangedRunnable)) {
+ mHandler.removeCallbacks(mOnConfigChangedRunnable);
+ }
+ mHandler.postDelayed(
+ mOnConfigChangedRunnable, BUFFER_MILLISECONDS_TO_PREVENT_UPDATE_FAILURE);
+ }
+
+ /**
+ * Handles click events of shortcuts.
+ *
+ * @param view the shortcut button being clicked.
+ */
+ public void handleClick(View view) {
+ mA11yMenuLayout.hideMenu();
+ }
+
@Override
public void onInterrupt() {
}
@Override
+ protected boolean onKeyEvent(KeyEvent event) {
+ if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+ mA11yMenuLayout.hideMenu();
+ }
+ return false;
+ }
+
+ @Override
public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+ if (mA11yMenuLayout.hideMenu()) {
+ mLastTimeTouchedOutside = SystemClock.uptimeMillis();
+ }
+ }
return false;
}
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
index e3401a9..337814e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -116,7 +116,7 @@
shortcutIconButton.setOnClickListener(
(View v) -> {
// Handles shortcut click event by AccessibilityMenuService.
- // service.handleClick(v);
+ mService.handleClick(v);
});
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index c510b87..cec503c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -66,7 +66,7 @@
public static final int LARGE_GRID_COLUMN_COUNT = 2;
/** Temporary measure to test both item types. */
- private static final boolean USE_LARGE_ITEMS = true;
+ private static final boolean USE_LARGE_ITEMS = false;
/**
* Returns the number of items in the grid view.
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 9a9236b..a3ed085 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -237,13 +237,17 @@
openedDialogs.firstOrNull {
it.dialog.window.decorView.viewRootImpl == controller.viewRoot
}
- val animateFrom =
+ val controller =
animatedParent?.dialogContentWithBackground?.let {
Controller.fromView(it, controller.cuj)
}
?: controller
- if (animatedParent == null && animateFrom !is LaunchableView) {
+ if (
+ animatedParent == null &&
+ controller is ViewDialogLaunchAnimatorController &&
+ controller.source !is LaunchableView
+ ) {
// Make sure the View we launch from implements LaunchableView to avoid visibility
// issues. Given that we don't own dialog decorViews so we can't enforce it for launches
// from a dialog.
@@ -272,7 +276,7 @@
launchAnimator,
callback,
interactionJankMonitor,
- animateFrom,
+ controller,
onDialogDismissed = { openedDialogs.remove(it) },
dialog = dialog,
animateBackgroundBoundsChange,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index dfac02d..26aa0e8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -26,6 +26,7 @@
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.InsetDrawable
import android.graphics.drawable.LayerDrawable
+import android.graphics.drawable.StateListDrawable
import android.util.Log
import android.view.GhostView
import android.view.View
@@ -35,6 +36,7 @@
import com.android.internal.jank.InteractionJankMonitor
import java.util.LinkedList
import kotlin.math.min
+import kotlin.math.roundToInt
private const val TAG = "GhostedViewLaunchAnimatorController"
@@ -49,7 +51,9 @@
* Note: Avoid instantiating this directly and call [ActivityLaunchAnimator.Controller.fromView]
* whenever possible instead.
*/
-open class GhostedViewLaunchAnimatorController @JvmOverloads constructor(
+open class GhostedViewLaunchAnimatorController
+@JvmOverloads
+constructor(
/** The view that will be ghosted and from which the background will be extracted. */
private val ghostedView: View,
@@ -145,7 +149,8 @@
val gradient = findGradientDrawable(drawable) ?: return 0f
// TODO(b/184121838): Support more than symmetric top & bottom radius.
- return gradient.cornerRadii?.get(CORNER_RADIUS_TOP_INDEX) ?: gradient.cornerRadius
+ val radius = gradient.cornerRadii?.get(CORNER_RADIUS_TOP_INDEX) ?: gradient.cornerRadius
+ return radius * ghostedView.scaleX
}
/** Return the current bottom corner radius of the background. */
@@ -154,7 +159,8 @@
val gradient = findGradientDrawable(drawable) ?: return 0f
// TODO(b/184121838): Support more than symmetric top & bottom radius.
- return gradient.cornerRadii?.get(CORNER_RADIUS_BOTTOM_INDEX) ?: gradient.cornerRadius
+ val radius = gradient.cornerRadii?.get(CORNER_RADIUS_BOTTOM_INDEX) ?: gradient.cornerRadius
+ return radius * ghostedView.scaleX
}
override fun createAnimatorState(): LaunchAnimator.State {
@@ -173,9 +179,13 @@
ghostedView.getLocationOnScreen(ghostedViewLocation)
val insets = backgroundInsets
state.top = ghostedViewLocation[1] + insets.top
- state.bottom = ghostedViewLocation[1] + ghostedView.height - insets.bottom
+ state.bottom =
+ ghostedViewLocation[1] + (ghostedView.height * ghostedView.scaleY).roundToInt() -
+ insets.bottom
state.left = ghostedViewLocation[0] + insets.left
- state.right = ghostedViewLocation[0] + ghostedView.width - insets.right
+ state.right =
+ ghostedViewLocation[0] + (ghostedView.width * ghostedView.scaleX).roundToInt() -
+ insets.right
}
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
@@ -341,6 +351,10 @@
}
}
+ if (drawable is StateListDrawable) {
+ return findGradientDrawable(drawable.current)
+ }
+
return null
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
index 46d5a5c..9257f99 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
@@ -25,7 +25,7 @@
/** A [DialogLaunchAnimator.Controller] that can animate a [View] from/to a dialog. */
class ViewDialogLaunchAnimatorController
internal constructor(
- private val source: View,
+ internal val source: View,
override val cuj: DialogCuj?,
) : DialogLaunchAnimator.Controller {
override val viewRoot: ViewRootImpl?
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetector.kt
new file mode 100644
index 0000000..1f6e603
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetector.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UFile
+import org.jetbrains.uast.UImportStatement
+
+/**
+ * Detects violations of the Dependency Rule of Clean Architecture.
+ *
+ * The rule states that code in each layer may only depend on code in the same layer or the layer
+ * directly "beneath" that layer in the layer diagram.
+ *
+ * In System UI, we have three layers; from top to bottom, they are: ui, domain, and data. As a
+ * convention, was used packages with those names to place code in the appropriate layer. We also
+ * make an exception and allow for shared models to live under a separate package named "shared" to
+ * avoid code duplication.
+ *
+ * For more information, please see go/sysui-arch.
+ */
+@Suppress("UnstableApiUsage")
+class CleanArchitectureDependencyViolationDetector : Detector(), Detector.UastScanner {
+ override fun getApplicableUastTypes(): List<Class<out UElement>> {
+ return listOf(UFile::class.java)
+ }
+
+ override fun createUastHandler(context: JavaContext): UElementHandler {
+ return object : UElementHandler() {
+ override fun visitFile(node: UFile) {
+ // Check which Clean Architecture layer this file belongs to:
+ matchingLayer(node.packageName)?.let { layer ->
+ // The file matches with a Clean Architecture layer. Let's check all of its
+ // imports.
+ node.imports.forEach { importStatement ->
+ visitImportStatement(context, layer, importStatement)
+ }
+ }
+ }
+ }
+ }
+
+ private fun visitImportStatement(
+ context: JavaContext,
+ layer: Layer,
+ importStatement: UImportStatement,
+ ) {
+ val importText = importStatement.importReference?.asSourceString() ?: return
+ val importedLayer = matchingLayer(importText) ?: return
+
+ // Now check whether the layer of the file may depend on the layer of the import.
+ if (!layer.mayDependOn(importedLayer)) {
+ context.report(
+ issue = ISSUE,
+ scope = importStatement,
+ location = context.getLocation(importStatement),
+ message =
+ "The ${layer.packageNamePart} layer may not depend on" +
+ " the ${importedLayer.packageNamePart} layer.",
+ )
+ }
+ }
+
+ private fun matchingLayer(packageName: String): Layer? {
+ val packageNameParts = packageName.split(".").toSet()
+ return Layer.values()
+ .filter { layer -> packageNameParts.contains(layer.packageNamePart) }
+ .takeIf { it.size == 1 }
+ ?.first()
+ }
+
+ private enum class Layer(
+ val packageNamePart: String,
+ val canDependOn: Set<Layer>,
+ ) {
+ SHARED(
+ packageNamePart = "shared",
+ canDependOn = emptySet(), // The shared layer may not depend on any other layer.
+ ),
+ DATA(
+ packageNamePart = "data",
+ canDependOn = setOf(SHARED),
+ ),
+ DOMAIN(
+ packageNamePart = "domain",
+ canDependOn = setOf(SHARED, DATA),
+ ),
+ UI(
+ packageNamePart = "ui",
+ canDependOn = setOf(DOMAIN, SHARED),
+ ),
+ ;
+
+ fun mayDependOn(otherLayer: Layer): Boolean {
+ return this == otherLayer || canDependOn.contains(otherLayer)
+ }
+ }
+
+ companion object {
+ @JvmStatic
+ val ISSUE =
+ Issue.create(
+ id = "CleanArchitectureDependencyViolation",
+ briefDescription = "Violation of the Clean Architecture Dependency Rule.",
+ explanation =
+ """
+ Following the \"Dependency Rule\" from Clean Architecture, every layer of code \
+ can only depend code in its own layer or code in the layer directly \
+ \"beneath\" it. Therefore, the UI layer can only depend on the" Domain layer \
+ and the Domain layer can only depend on the Data layer. We" do make an \
+ exception to allow shared models to exist and be shared across layers by \
+ placing them under shared/model, which should be done with care. For more \
+ information about Clean Architecture in System UI, please see go/sysui-arch. \
+ NOTE: if your code is not using Clean Architecture, please feel free to ignore \
+ this warning.
+ """,
+ category = Category.CORRECTNESS,
+ priority = 8,
+ severity = Severity.WARNING,
+ implementation =
+ Implementation(
+ CleanArchitectureDependencyViolationDetector::class.java,
+ Scope.JAVA_FILE_SCOPE,
+ ),
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 3f334c1c..254a6fb 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -27,9 +27,11 @@
class SystemUIIssueRegistry : IssueRegistry() {
override val issues: List<Issue>
- get() = listOf(
+ get() =
+ listOf(
BindServiceOnMainThreadDetector.ISSUE,
BroadcastSentViaContextDetector.ISSUE,
+ CleanArchitectureDependencyViolationDetector.ISSUE,
SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
NonInjectedMainThreadDetector.ISSUE,
@@ -37,7 +39,7 @@
SoftwareBitmapDetector.ISSUE,
NonInjectedServiceDetector.ISSUE,
StaticSettingsProviderDetector.ISSUE
- )
+ )
override val api: Int
get() = CURRENT_API
@@ -45,9 +47,9 @@
get() = 8
override val vendor: Vendor =
- Vendor(
- vendorName = "Android",
- feedbackUrl = "http://b/issues/new?component=78010",
- contact = "jernej@google.com"
- )
+ Vendor(
+ vendorName = "Android",
+ feedbackUrl = "http://b/issues/new?component=78010",
+ contact = "jernej@google.com"
+ )
}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
new file mode 100644
index 0000000..a4b59fd
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.checks.infrastructure.TestMode
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Ignore
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+@Ignore("b/254533331")
+class CleanArchitectureDependencyViolationDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector {
+ return CleanArchitectureDependencyViolationDetector()
+ }
+
+ override fun getIssues(): List<Issue> {
+ return listOf(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ }
+
+ @Test
+ fun `No violations`() {
+ lint()
+ .files(
+ *LEGITIMATE_FILES,
+ )
+ .issues(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ .run()
+ .expectWarningCount(0)
+ }
+
+ @Test
+ fun `Violation - domain depends on ui`() {
+ lint()
+ .files(
+ *LEGITIMATE_FILES,
+ TestFiles.kotlin(
+ """
+ package test.domain.interactor
+
+ import test.ui.viewmodel.ViewModel
+
+ class BadClass(
+ private val viewModel: ViewModel,
+ )
+ """.trimIndent()
+ )
+ )
+ .issues(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expect(
+ expectedText =
+ """
+ src/test/domain/interactor/BadClass.kt:3: Warning: The domain layer may not depend on the ui layer. [CleanArchitectureDependencyViolation]
+ import test.ui.viewmodel.ViewModel
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun `Violation - ui depends on data`() {
+ lint()
+ .files(
+ *LEGITIMATE_FILES,
+ TestFiles.kotlin(
+ """
+ package test.ui.viewmodel
+
+ import test.data.repository.Repository
+
+ class BadClass(
+ private val repository: Repository,
+ )
+ """.trimIndent()
+ )
+ )
+ .issues(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expect(
+ expectedText =
+ """
+ src/test/ui/viewmodel/BadClass.kt:3: Warning: The ui layer may not depend on the data layer. [CleanArchitectureDependencyViolation]
+ import test.data.repository.Repository
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun `Violation - shared depends on all other layers`() {
+ lint()
+ .files(
+ *LEGITIMATE_FILES,
+ TestFiles.kotlin(
+ """
+ package test.shared.model
+
+ import test.data.repository.Repository
+ import test.domain.interactor.Interactor
+ import test.ui.viewmodel.ViewModel
+
+ class BadClass(
+ private val repository: Repository,
+ private val interactor: Interactor,
+ private val viewmodel: ViewModel,
+ )
+ """.trimIndent()
+ )
+ )
+ .issues(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(3)
+ .expect(
+ expectedText =
+ """
+ src/test/shared/model/BadClass.kt:3: Warning: The shared layer may not depend on the data layer. [CleanArchitectureDependencyViolation]
+ import test.data.repository.Repository
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ src/test/shared/model/BadClass.kt:4: Warning: The shared layer may not depend on the domain layer. [CleanArchitectureDependencyViolation]
+ import test.domain.interactor.Interactor
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ src/test/shared/model/BadClass.kt:5: Warning: The shared layer may not depend on the ui layer. [CleanArchitectureDependencyViolation]
+ import test.ui.viewmodel.ViewModel
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 3 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun `Violation - data depends on domain`() {
+ lint()
+ .files(
+ *LEGITIMATE_FILES,
+ TestFiles.kotlin(
+ """
+ package test.data.repository
+
+ import test.domain.interactor.Interactor
+
+ class BadClass(
+ private val interactor: Interactor,
+ )
+ """.trimIndent()
+ )
+ )
+ .issues(
+ CleanArchitectureDependencyViolationDetector.ISSUE,
+ )
+ .testModes(TestMode.DEFAULT)
+ .run()
+ .expectWarningCount(1)
+ .expect(
+ expectedText =
+ """
+ src/test/data/repository/BadClass.kt:3: Warning: The data layer may not depend on the domain layer. [CleanArchitectureDependencyViolation]
+ import test.domain.interactor.Interactor
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 0 errors, 1 warnings
+ """,
+ )
+ }
+
+ companion object {
+ private val MODEL_FILE =
+ TestFiles.kotlin(
+ """
+ package test.shared.model
+
+ import test.some.other.thing.SomeOtherThing
+
+ data class Model(
+ private val name: String,
+ )
+ """.trimIndent()
+ )
+ private val REPOSITORY_FILE =
+ TestFiles.kotlin(
+ """
+ package test.data.repository
+
+ import test.shared.model.Model
+ import test.some.other.thing.SomeOtherThing
+
+ class Repository {
+ private val models = listOf(
+ Model("one"),
+ Model("two"),
+ Model("three"),
+ )
+
+ fun getModels(): List<Model> {
+ return models
+ }
+ }
+ """.trimIndent()
+ )
+ private val INTERACTOR_FILE =
+ TestFiles.kotlin(
+ """
+ package test.domain.interactor
+
+ import test.data.repository.Repository
+ import test.shared.model.Model
+
+ class Interactor(
+ private val repository: Repository,
+ ) {
+ fun getModels(): List<Model> {
+ return repository.getModels()
+ }
+ }
+ """.trimIndent()
+ )
+ private val VIEW_MODEL_FILE =
+ TestFiles.kotlin(
+ """
+ package test.ui.viewmodel
+
+ import test.domain.interactor.Interactor
+ import test.some.other.thing.SomeOtherThing
+
+ class ViewModel(
+ private val interactor: Interactor,
+ ) {
+ fun getNames(): List<String> {
+ return interactor.getModels().map { model -> model.name }
+ }
+ }
+ """.trimIndent()
+ )
+ private val NON_CLEAN_ARCHITECTURE_FILE =
+ TestFiles.kotlin(
+ """
+ package test.some.other.thing
+
+ import test.data.repository.Repository
+ import test.domain.interactor.Interactor
+ import test.ui.viewmodel.ViewModel
+
+ class SomeOtherThing {
+ init {
+ val viewModel = ViewModel(
+ interactor = Interactor(
+ repository = Repository(),
+ ),
+ )
+ }
+ }
+ """.trimIndent()
+ )
+ private val LEGITIMATE_FILES =
+ arrayOf(
+ MODEL_FILE,
+ REPOSITORY_FILE,
+ INTERACTOR_FILE,
+ VIEW_MODEL_FILE,
+ NON_CLEAN_ARCHITECTURE_FILE,
+ )
+ }
+}
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index 8917013..9b4c21e 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -8,105 +8,110 @@
- [User's guide](https://google.github.io/dagger/users-guide)
-TODO: Add some links.
-
## State of the world
-Dagger 2 has been turned on for SystemUI and a early first pass has been taken
-for converting everything in [Dependency.java](packages/systemui/src/com/android/systemui/Dependency.java)
-to use Dagger. Since a lot of SystemUI depends on Dependency, stubs have been added to Dependency
-to proxy any gets through to the instances provided by dagger, this will allow migration of SystemUI
-through a number of CLs.
+Dagger 2 has been turned on for SystemUI and much of
+[Dependency.java](../src/com/android/systemui/Dependency.java)
+has been converted to use Dagger. Since a lot of SystemUI depends on Dependency,
+stubs have been added to Dependency to proxy any gets through to the instances
+provided by dagger, this will allow migration of SystemUI through a number of CLs.
### How it works in SystemUI
+There are three high level "scopes" of concern in SystemUI. They all represent
+singleton scopes, but serve different purposes.
+
+* `@Singleton` - Instances that are shared everywhere. There isn't a lot of
+ code in this scope. Things like the main thread, and Android Framework
+ provided instances mostly.
+* `@WMShell` - WindowManager related code in the SystemUI process. We don't
+ want this code relying on the rest of SystemUI, and we don't want the rest
+ of SystemUI peeking into its internals, so it runs in its own Subcomponent.
+* `@SysUISingleton` - Most of what would be considered "SystemUI". Most feature
+ work by SystemUI developers goes into this scope. Useful interfaces from
+ WindowManager are made available inside this Subcomponent.
+
+The root dagger graph is created by an instance of `SystemUIInitializer`.
+See [README.md](../README.md) for more details.
For the classes that we're using in Dependency and are switching to dagger, the
equivalent dagger version is using `@Singleton` and therefore only has one instance.
To have the single instance span all of SystemUI and be easily accessible for
other components, there is a single root `@Component` that exists that generates
-these. The component lives in [SystemUIFactory](packages/systemui/src/com/android/systemui/SystemUIFactory.java)
-and is called `SystemUIRootComponent`.
-
-```java
-
-@Singleton
-@Component(modules = {SystemUIFactory.class, DependencyProvider.class, DependencyBinder.class,
- ContextHolder.class})
-public interface SystemUIRootComponent {
- @Singleton
- Dependency.DependencyInjector createDependency();
-}
-```
-
-The root component is composed of root modules, which in turn provide the global singleton
-dependencies across all of SystemUI.
-
-- `SystemUIFactory` `@Provides` dependencies that need to be overridden by SystemUI
-variants (like other form factors e.g. Car).
-
-- `DependencyBinder` creates the mapping from interfaces to implementation classes.
-
-- `DependencyProvider` provides or binds any remaining depedencies required.
-
-### Adding injection to a new SystemUI object
-
-SystemUI object are made injectable by adding an entry in `SystemUIBinder`. SystemUIApplication uses
-information in that file to locate and construct an instance of the requested SystemUI class.
+these. The component lives in
+[ReferenceGlobalRootComponent.java](../src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java).
### Adding a new injectable object
-First tag the constructor with `@Inject`. Also tag it with `@Singleton` if only one
-instance should be created.
+First annotate the constructor with `@Inject`. Also annotate it with
+`@SysUISingleton` if only one instance should be created.
-```java
-@Singleton
-public class SomethingController {
- @Inject
- public SomethingController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- // context and mainHandler will be automatically populated.
- }
+```kotlin
+@SysUISingleton
+class FeatureStartable
+@Inject
+constructor(
+/* ... */
+) {
+ // ...
}
```
-If you have an interface class and an implementation class, dagger needs to know
-how to map it. The simplest way to do this is to add an `@Provides` method to
-DependencyProvider. The type of the return value tells dagger which dependency it's providing.
+If you have an interface class and an implementation class, Dagger needs to
+know how to map it. The simplest way to do this is to add an `@Binds` method
+in a module. The type of the return value tells dagger which dependency it's
+providing:
-```java
-public class DependencyProvider {
- //...
- @Singleton
- @Provides
- public SomethingController provideSomethingController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- return new SomethingControllerImpl(context, mainHandler);
- }
+```kotlin
+@Module
+abstract class FeatureModule {
+ @Binds
+ abstract fun bindsFeature(impl: FeatureImpl): Feature
}
```
-If you need to access this from Dependency#get, then add an adapter to Dependency
-that maps to the instance provided by Dagger. The changes should be similar
-to the following diff.
+If you have a class that you want to make injectable that has can not
+be easily constructed by Dagger, write a `@Provides` method for it:
-```java
-public class Dependency {
- //...
- @Inject Lazy<SomethingController> mSomethingController;
- //...
- public void start() {
- //...
- mProviders.put(SomethingController.class, mSomethingController::get);
- }
+```kotlin
+@Module
+abstract class FeatureModule {
+ @Module
+ companion object {
+ @Provides
+ fun providesFeature(ctx: Context): Feature {
+ return FeatureImpl.constructFromContext(ctx)
+ }
+ }
}
```
+### Module Organization
+
+Please define your modules on _at least_ per-package level. If the scope of a
+package grows to encompass a great number of features, create per-feature
+modules.
+
+**Do not create catch-all modules.** Those quickly grow unwieldy and
+unmaintainable. Any that exist today should be refactored into obsolescence.
+
+You can then include your module in one of three places:
+
+1) Within another module that depends on it. Ideally, this creates a clean
+ dependency graph between features and utilities.
+2) For features that should exist in all versions of SystemUI (AOSP and
+ any variants), include the module in
+ [SystemUIModule.java](../src/com/android/systemui/dagger/SystemUIModule.java).
+3) For features that should exist only in AOSP, include the module in
+ [ReferenceSystemUIModule.java](../src/com/android/systemui/dagger/ReferenceSystemUIModule.java).
+ Similarly, if you are working on a custom version of SystemUI and have code
+ specific to your version, include it in a module specific to your version.
+
### Using injection with Fragments
Fragments are created as part of the FragmentManager, so they need to be
setup so the manager knows how to create them. To do that, add a method
to com.android.systemui.fragments.FragmentService$FragmentCreator that
-returns your fragment class. Thats all thats required, once the method
+returns your fragment class. That is all that is required, once the method
exists, FragmentService will automatically pick it up and use injection
whenever your fragment needs to be created.
@@ -123,48 +128,11 @@
FragmentHostManager.get(view).create(NavigationBarFragment.class);
```
-### Using injection with Views
-
-DO NOT ADD NEW VIEW INJECTION. VIEW INJECTION IS BEING ACTIVELY DEPRECATED.
-
-Needing to inject objects into your View's constructor generally implies you
-are doing more work in your presentation layer than is advisable.
-Instead, create an injected controller for you view, inject into the
-controller, and then attach the view to the controller after inflation.
-
-View injection generally causes headaches while testing, as inflating a view
-(which may in turn inflate other views) implicitly causes a Dagger graph to
-be stood up, which may or may not contain the appropriately
-faked/mocked/stubbed objects. It is a hard to control process.
-
## Updating Dagger2
We depend on the Dagger source found in external/dagger2. We should automatically pick up on updates
when that repository is updated.
-
-*Deprecated:*
-
-Binaries can be downloaded from https://repo1.maven.org/maven2/com/google/dagger/ and then loaded
-into
-[/prebuilts/tools/common/m2/repository/com/google/dagger/](http://cs/android/prebuilts/tools/common/m2/repository/com/google/dagger/)
-
-The following commands should work, substituting in the version that you are looking for:
-
-````
-cd prebuilts/tools/common/m2/repository/com/google/dagger/
-
-wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger/2.28.1/
-
-wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.28.1/
-
-wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-spi/2.28.1/
-
-wget -r -np -nH --cut-dirs=4 -erobots=off -R "index.html*" -U "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36" https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.28.1/
-````
-
-Then update `prebuilts/tools/common/m2/Android.bp` to point at your new jars.
## TODO List
- - Eliminate usages of Dependency#get
- - Add links in above TODO
+ - Eliminate usages of Dependency#get: http://b/hotlists/3940788
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index 2148cb0..6d970b3 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,6 +1,5 @@
+packages/SystemUI
-packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
--packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -322,8 +321,8 @@
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
--packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
--packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
-packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt
-packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
-packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index dee0f5c..314c736 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -80,6 +80,7 @@
internal class HueVibrantSecondary() : Hue {
val hueToRotations = listOf(Pair(0, 18), Pair(41, 15), Pair(61, 10), Pair(101, 12),
Pair(131, 15), Pair(181, 18), Pair(251, 15), Pair(301, 12), Pair(360, 12))
+
override fun get(sourceColor: Cam): Double {
return getHueRotation(sourceColor.hue, hueToRotations)
}
@@ -88,6 +89,7 @@
internal class HueVibrantTertiary() : Hue {
val hueToRotations = listOf(Pair(0, 35), Pair(41, 30), Pair(61, 20), Pair(101, 25),
Pair(131, 30), Pair(181, 35), Pair(251, 30), Pair(301, 25), Pair(360, 25))
+
override fun get(sourceColor: Cam): Double {
return getHueRotation(sourceColor.hue, hueToRotations)
}
@@ -96,6 +98,7 @@
internal class HueExpressiveSecondary() : Hue {
val hueToRotations = listOf(Pair(0, 45), Pair(21, 95), Pair(51, 45), Pair(121, 20),
Pair(151, 45), Pair(191, 90), Pair(271, 45), Pair(321, 45), Pair(360, 45))
+
override fun get(sourceColor: Cam): Double {
return getHueRotation(sourceColor.hue, hueToRotations)
}
@@ -104,6 +107,7 @@
internal class HueExpressiveTertiary() : Hue {
val hueToRotations = listOf(Pair(0, 120), Pair(21, 120), Pair(51, 20), Pair(121, 45),
Pair(151, 20), Pair(191, 15), Pair(271, 20), Pair(321, 120), Pair(360, 120))
+
override fun get(sourceColor: Cam): Double {
return getHueRotation(sourceColor.hue, hueToRotations)
}
@@ -148,11 +152,11 @@
}
internal class CoreSpec(
- val a1: TonalSpec,
- val a2: TonalSpec,
- val a3: TonalSpec,
- val n1: TonalSpec,
- val n2: TonalSpec
+ val a1: TonalSpec,
+ val a2: TonalSpec,
+ val a3: TonalSpec,
+ val n1: TonalSpec,
+ val n2: TonalSpec
)
enum class Style(internal val coreSpec: CoreSpec) {
@@ -214,51 +218,86 @@
)),
}
+class TonalPalette {
+ val shadeKeys = listOf(10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
+ val allShades: List<Int>
+ val allShadesMapped: Map<Int, Int>
+ val baseColor: Int
+
+ internal constructor(spec: TonalSpec, seedColor: Int) {
+ val seedCam = Cam.fromInt(seedColor)
+ allShades = spec.shades(seedCam)
+ allShadesMapped = shadeKeys.zip(allShades).toMap()
+
+ val h = spec.hue.get(seedCam).toFloat()
+ val c = spec.chroma.get(seedCam).toFloat()
+ baseColor = ColorUtils.CAMToColor(h, c, CamUtils.lstarFromInt(seedColor))
+ }
+
+ val s10: Int get() = this.allShades[0]
+ val s50: Int get() = this.allShades[1]
+ val s100: Int get() = this.allShades[2]
+ val s200: Int get() = this.allShades[3]
+ val s300: Int get() = this.allShades[4]
+ val s400: Int get() = this.allShades[5]
+ val s500: Int get() = this.allShades[6]
+ val s600: Int get() = this.allShades[7]
+ val s700: Int get() = this.allShades[8]
+ val s800: Int get() = this.allShades[9]
+ val s900: Int get() = this.allShades[10]
+ val s1000: Int get() = this.allShades[11]
+}
+
class ColorScheme(
- @ColorInt val seed: Int,
- val darkTheme: Boolean,
- val style: Style = Style.TONAL_SPOT
+ @ColorInt val seed: Int,
+ val darkTheme: Boolean,
+ val style: Style = Style.TONAL_SPOT
) {
- val accent1: List<Int>
- val accent2: List<Int>
- val accent3: List<Int>
- val neutral1: List<Int>
- val neutral2: List<Int>
+ val accent1: TonalPalette
+ val accent2: TonalPalette
+ val accent3: TonalPalette
+ val neutral1: TonalPalette
+ val neutral2: TonalPalette
constructor(@ColorInt seed: Int, darkTheme: Boolean) :
this(seed, darkTheme, Style.TONAL_SPOT)
@JvmOverloads
constructor(
- wallpaperColors: WallpaperColors,
- darkTheme: Boolean,
- style: Style = Style.TONAL_SPOT
+ wallpaperColors: WallpaperColors,
+ darkTheme: Boolean,
+ style: Style = Style.TONAL_SPOT
) :
this(getSeedColor(wallpaperColors, style != Style.CONTENT), darkTheme, style)
+ val allHues: List<TonalPalette>
+ get() {
+ return listOf(accent1, accent2, accent3, neutral1, neutral2)
+ }
+
val allAccentColors: List<Int>
get() {
val allColors = mutableListOf<Int>()
- allColors.addAll(accent1)
- allColors.addAll(accent2)
- allColors.addAll(accent3)
+ allColors.addAll(accent1.allShades)
+ allColors.addAll(accent2.allShades)
+ allColors.addAll(accent3.allShades)
return allColors
}
val allNeutralColors: List<Int>
get() {
val allColors = mutableListOf<Int>()
- allColors.addAll(neutral1)
- allColors.addAll(neutral2)
+ allColors.addAll(neutral1.allShades)
+ allColors.addAll(neutral2.allShades)
return allColors
}
val backgroundColor
- get() = ColorUtils.setAlphaComponent(if (darkTheme) neutral1[8] else neutral1[0], 0xFF)
+ get() = ColorUtils.setAlphaComponent(if (darkTheme) neutral1.s700 else neutral1.s10, 0xFF)
val accentColor
- get() = ColorUtils.setAlphaComponent(if (darkTheme) accent1[2] else accent1[6], 0xFF)
+ get() = ColorUtils.setAlphaComponent(if (darkTheme) accent1.s100 else accent1.s500, 0xFF)
init {
val proposedSeedCam = Cam.fromInt(seed)
@@ -269,24 +308,26 @@
} else {
seed
}
- val camSeed = Cam.fromInt(seedArgb)
- accent1 = style.coreSpec.a1.shades(camSeed)
- accent2 = style.coreSpec.a2.shades(camSeed)
- accent3 = style.coreSpec.a3.shades(camSeed)
- neutral1 = style.coreSpec.n1.shades(camSeed)
- neutral2 = style.coreSpec.n2.shades(camSeed)
+
+ accent1 = TonalPalette(style.coreSpec.a1, seedArgb)
+ accent2 = TonalPalette(style.coreSpec.a2, seedArgb)
+ accent3 = TonalPalette(style.coreSpec.a3, seedArgb)
+ neutral1 = TonalPalette(style.coreSpec.n1, seedArgb)
+ neutral2 = TonalPalette(style.coreSpec.n2, seedArgb)
}
+ val shadeCount get() = this.accent1.allShades.size
+
override fun toString(): String {
return "ColorScheme {\n" +
" seed color: ${stringForColor(seed)}\n" +
" style: $style\n" +
" palettes: \n" +
- " ${humanReadable("PRIMARY", accent1)}\n" +
- " ${humanReadable("SECONDARY", accent2)}\n" +
- " ${humanReadable("TERTIARY", accent3)}\n" +
- " ${humanReadable("NEUTRAL", neutral1)}\n" +
- " ${humanReadable("NEUTRAL VARIANT", neutral2)}\n" +
+ " ${humanReadable("PRIMARY", accent1.allShades)}\n" +
+ " ${humanReadable("SECONDARY", accent2.allShades)}\n" +
+ " ${humanReadable("TERTIARY", accent3.allShades)}\n" +
+ " ${humanReadable("NEUTRAL", neutral1.allShades)}\n" +
+ " ${humanReadable("NEUTRAL VARIANT", neutral2.allShades)}\n" +
"}"
}
@@ -385,7 +426,8 @@
val existingSeedNearby = seeds.find {
val hueA = intToCam[int]!!.hue
val hueB = intToCam[it]!!.hue
- hueDiff(hueA, hueB) < i } != null
+ hueDiff(hueA, hueB) < i
+ } != null
if (existingSeedNearby) {
continue
}
@@ -460,9 +502,9 @@
}
private fun huePopulations(
- camByColor: Map<Int, Cam>,
- populationByColor: Map<Int, Double>,
- filter: Boolean = true
+ camByColor: Map<Int, Cam>,
+ populationByColor: Map<Int, Double>,
+ filter: Boolean = true
): List<Double> {
val huePopulation = List(size = 360, init = { 0.0 }).toMutableList()
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index 7709f21..fb1c454 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -29,6 +29,7 @@
"src/**/*.java",
"src/**/*.kt",
"bcsmartspace/src/**/*.java",
+ "bcsmartspace/src/**/*.kt",
],
static_libs: [
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
new file mode 100644
index 0000000..509f022
--- /dev/null
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.plugins
+
+// TODO(b/265360975): Evaluate this plugin approach.
+/** Plugin to provide BC smartspace configuration */
+interface BcSmartspaceConfigPlugin {
+ /** Gets default date/weather disabled status. */
+ val isDefaultDateWeatherDisabled: Boolean
+}
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 51f5baa..bc6e5ec 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -94,6 +94,11 @@
void registerDataProvider(BcSmartspaceDataPlugin plugin);
/**
+ * Sets {@link BcSmartspaceConfigPlugin}.
+ */
+ void registerConfigProvider(BcSmartspaceConfigPlugin configProvider);
+
+ /**
* Primary color for unprotected text
*/
void setPrimaryTextColor(int color);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index d3fabac..faf1b78 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -21,6 +21,7 @@
import android.net.Uri
import android.os.Handler
import android.os.Looper
+import android.os.Trace
import android.provider.Settings
/**
@@ -51,14 +52,21 @@
}
}
+ private fun clearCache() {
+ Trace.beginSection("LogcatEchoTrackerDebug#clearCache")
+ cachedBufferLevels.clear()
+ Trace.endSection()
+ }
+
private fun attach(mainLooper: Looper) {
+ Trace.beginSection("LogcatEchoTrackerDebug#attach")
contentResolver.registerContentObserver(
Settings.Global.getUriFor(BUFFER_PATH),
true,
object : ContentObserver(Handler(mainLooper)) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
- cachedBufferLevels.clear()
+ clearCache()
}
}
)
@@ -69,10 +77,11 @@
object : ContentObserver(Handler(mainLooper)) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
- cachedTagLevels.clear()
+ clearCache()
}
}
)
+ Trace.endSection()
}
/** Whether [bufferName] should echo messages of [level] or higher to logcat. */
@@ -97,9 +106,12 @@
private fun readSetting(path: String): LogLevel {
return try {
+ Trace.beginSection("LogcatEchoTrackerDebug#readSetting")
parseProp(Settings.Global.getString(contentResolver, path))
} catch (_: Settings.SettingNotFoundException) {
DEFAULT_LEVEL
+ } finally {
+ Trace.endSection()
}
}
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index 81f64ca..787f885 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Entsperre dein Smartphone für weitere Optionen"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Entsperre dein Tablet für weitere Optionen"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Entsperre dein Gerät für weitere Optionen"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Wird auf diesem Smartphone abgespielt"</string>
- <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Wird auf diesem Tablet abgespielt"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Wiedergabe läuft auf diesem Smartphone"</string>
+ <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Wiedergabe läuft auf diesem Tablet"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-fr/strings.xml b/packages/SystemUI/res-product/values-fr/strings.xml
index c255973..817f4a3 100644
--- a/packages/SystemUI/res-product/values-fr/strings.xml
+++ b/packages/SystemUI/res-product/values-fr/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Déverrouillez votre téléphone pour obtenir plus d\'options"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Déverrouillez votre tablette pour obtenir plus d\'options"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour obtenir plus d\'options"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Lecture sur ce téléphone…"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Lecture sur ce téléphone"</string>
<string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Lecture sur cette tablette…"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-ka/strings.xml b/packages/SystemUI/res-product/values-ka/strings.xml
index 60b7b0c..8d423a2 100644
--- a/packages/SystemUI/res-product/values-ka/strings.xml
+++ b/packages/SystemUI/res-product/values-ka/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტელეფონი"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი ტაბლეტი"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი მოწყობილობა"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"უკრავს ტელეფონზე"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"უკრავს ამ ტელეფონზე"</string>
<string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"უკრავს ამ ტაბლეტზე"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pt-rBR/strings.xml b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
index c91d377..004a499 100644
--- a/packages/SystemUI/res-product/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Mídia aberta neste smartphone"</string>
- <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia aberta neste tablet"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Mídia tocando neste smartphone"</string>
+ <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia tocando neste tablet"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-pt/strings.xml b/packages/SystemUI/res-product/values-pt/strings.xml
index c91d377..004a499 100644
--- a/packages/SystemUI/res-product/values-pt/strings.xml
+++ b/packages/SystemUI/res-product/values-pt/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Desbloqueie seu smartphone para ver mais opções"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Desbloqueie seu tablet para ver mais opções"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Mídia aberta neste smartphone"</string>
- <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia aberta neste tablet"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Mídia tocando neste smartphone"</string>
+ <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia tocando neste tablet"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-uz/strings.xml b/packages/SystemUI/res-product/values-uz/strings.xml
index 48473f4..c10d54f 100644
--- a/packages/SystemUI/res-product/values-uz/strings.xml
+++ b/packages/SystemUI/res-product/values-uz/strings.xml
@@ -43,6 +43,6 @@
<string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Boshqa parametrlar uchun telefoningiz qulfini oching"</string>
<string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Boshqa parametrlar uchun planshetingiz qulfini oching"</string>
<string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Boshqa parametrlar uchun qurilmangiz qulfini oching"</string>
- <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Bu telefonda ijro etilmoqda"</string>
+ <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Bu telefonda ijro qilinmoqda"</string>
<string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Bu planshetda ijro etilmoqda"</string>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_camera.xml b/packages/SystemUI/res/drawable/ic_camera.xml
new file mode 100644
index 0000000..ef1406c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_camera.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,42Q5.8,42 4.9,41.1Q4,40.2 4,39V13.35Q4,12.15 4.9,11.25Q5.8,10.35 7,10.35H14.35L18,6H30L33.65,10.35H41Q42.2,10.35 43.1,11.25Q44,12.15 44,13.35V39Q44,40.2 43.1,41.1Q42.2,42 41,42ZM7,39H41Q41,39 41,39Q41,39 41,39V13.35Q41,13.35 41,13.35Q41,13.35 41,13.35H7Q7,13.35 7,13.35Q7,13.35 7,13.35V39Q7,39 7,39Q7,39 7,39ZM7,39Q7,39 7,39Q7,39 7,39V13.35Q7,13.35 7,13.35Q7,13.35 7,13.35Q7,13.35 7,13.35Q7,13.35 7,13.35V39Q7,39 7,39Q7,39 7,39ZM24,34.7Q27.5,34.7 30,32.225Q32.5,29.75 32.5,26.2Q32.5,22.7 30,20.2Q27.5,17.7 24,17.7Q20.45,17.7 17.975,20.2Q15.5,22.7 15.5,26.2Q15.5,29.75 17.975,32.225Q20.45,34.7 24,34.7ZM24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Q24,26.2 24,26.2Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_note_task_button.xml b/packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml
similarity index 92%
copy from packages/SystemUI/res/drawable/ic_note_task_button.xml
copy to packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml
index bb5e224..ee8d4883 100644
--- a/packages/SystemUI/res/drawable/ic_note_task_button.xml
+++ b/packages/SystemUI/res/drawable/ic_note_task_shortcut_keyguard.xml
@@ -19,10 +19,13 @@
android:viewportHeight="24"
android:viewportWidth="24">
<path
- android:fillColor="#636C6F"
+ android:fillAlpha="1"
+ android:fillColor="@android:color/white"
+ android:fillType="nonZero"
android:pathData="M17.6258,4.96L19.0358,6.37L7.4058,18.01L5.9958,16.6L17.6258,4.96ZM16.1358,3.62L4.1258,15.63L3.0158,19.83C2.9058,20.45 3.3858,21 3.9958,21C4.0558,21 4.1058,21 4.1658,20.99L8.3658,19.88L20.3758,7.86C20.7758,7.46 20.9958,6.93 20.9958,6.37C20.9958,5.81 20.7758,5.28 20.3758,4.88L19.1058,3.61C18.7158,3.22 18.1858,3 17.6258,3C17.0658,3 16.5358,3.22 16.1358,3.62Z" />
<path
- android:fillColor="#636C6F"
- android:fillType="evenOdd"
+ android:fillAlpha="1"
+ android:fillColor="@android:color/white"
+ android:fillType="nonZero"
android:pathData="M20.1936,15.3369C20.3748,16.3837 19.9151,17.5414 18.8846,18.7597C19.1546,18.872 19.4576,18.9452 19.7724,18.9867C20.0839,19.0278 20.3683,19.0325 20.5749,19.0266C20.6772,19.0236 20.7578,19.0181 20.8101,19.0138C20.8362,19.0116 20.855,19.0097 20.8657,19.0085L20.8754,19.0074L20.875,19.0075C21.4217,18.9385 21.9214,19.325 21.9918,19.8718C22.0624,20.4195 21.6756,20.9208 21.1279,20.9914L21,19.9996C21.1279,20.9914 21.1265,20.9916 21.1265,20.9916L21.1249,20.9918L21.1211,20.9923L21.1107,20.9935L21.0795,20.997C21.0542,20.9998 21.0199,21.0032 20.9775,21.0067C20.8929,21.0138 20.7753,21.0216 20.6323,21.0257C20.3481,21.0339 19.9533,21.0279 19.5109,20.9695C18.873,20.8854 18.0393,20.6793 17.3106,20.1662C16.9605,20.3559 16.5876,20.4952 16.2299,20.6003C15.5742,20.7927 14.8754,20.8968 14.2534,20.9534C13.6801,21.0055 13.4553,21.0037 13.1015,21.0008C13.0689,21.0005 13.0352,21.0002 13,21H12.8594C12.8214,21.0002 12.785,21.0006 12.7504,21.0009C12.6524,21.0019 12.5683,21.0027 12.5,21H12.0562C12.0277,21.0003 12.0054,21.0006 11.9926,21.001L11.9751,21H9L11,19H11.9795C11.9929,18.9997 12.0064,18.9997 12.0199,19H12.4117C12.4534,18.9996 12.4864,18.9995 12.5,19H12.9675C12.977,18.9999 12.9878,18.9999 13,19C13.0446,19.0003 13.0859,19.0007 13.1249,19.0011C13.4259,19.0038 13.591,19.0054 14.0723,18.9616C14.6201,18.9118 15.1795,18.8242 15.6665,18.6813C15.753,18.6559 15.8346,18.6295 15.9114,18.6022C15.0315,17.2981 14.7125,16.1044 15.015,15.0829C15.4095,13.7511 16.6784,13.2418 17.7026,13.2864C18.7262,13.3309 19.954,13.9529 20.1936,15.3369ZM16.9327,15.6508C16.873,15.8523 16.8651,16.3878 17.4697,17.334C18.2007,16.4284 18.2585,15.8839 18.2229,15.6781C18.1939,15.5108 18.0297,15.3025 17.6157,15.2845C17.2025,15.2665 16.9885,15.4626 16.9327,15.6508Z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_note_task_button.xml b/packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/ic_note_task_button.xml
rename to packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml
index bb5e224..7590182 100644
--- a/packages/SystemUI/res/drawable/ic_note_task_button.xml
+++ b/packages/SystemUI/res/drawable/ic_note_task_shortcut_widget.xml
@@ -19,10 +19,13 @@
android:viewportHeight="24"
android:viewportWidth="24">
<path
+ android:fillAlpha="1"
android:fillColor="#636C6F"
+ android:fillType="nonZero"
android:pathData="M17.6258,4.96L19.0358,6.37L7.4058,18.01L5.9958,16.6L17.6258,4.96ZM16.1358,3.62L4.1258,15.63L3.0158,19.83C2.9058,20.45 3.3858,21 3.9958,21C4.0558,21 4.1058,21 4.1658,20.99L8.3658,19.88L20.3758,7.86C20.7758,7.46 20.9958,6.93 20.9958,6.37C20.9958,5.81 20.7758,5.28 20.3758,4.88L19.1058,3.61C18.7158,3.22 18.1858,3 17.6258,3C17.0658,3 16.5358,3.22 16.1358,3.62Z" />
<path
+ android:fillAlpha="1"
android:fillColor="#636C6F"
- android:fillType="evenOdd"
+ android:fillType="nonZero"
android:pathData="M20.1936,15.3369C20.3748,16.3837 19.9151,17.5414 18.8846,18.7597C19.1546,18.872 19.4576,18.9452 19.7724,18.9867C20.0839,19.0278 20.3683,19.0325 20.5749,19.0266C20.6772,19.0236 20.7578,19.0181 20.8101,19.0138C20.8362,19.0116 20.855,19.0097 20.8657,19.0085L20.8754,19.0074L20.875,19.0075C21.4217,18.9385 21.9214,19.325 21.9918,19.8718C22.0624,20.4195 21.6756,20.9208 21.1279,20.9914L21,19.9996C21.1279,20.9914 21.1265,20.9916 21.1265,20.9916L21.1249,20.9918L21.1211,20.9923L21.1107,20.9935L21.0795,20.997C21.0542,20.9998 21.0199,21.0032 20.9775,21.0067C20.8929,21.0138 20.7753,21.0216 20.6323,21.0257C20.3481,21.0339 19.9533,21.0279 19.5109,20.9695C18.873,20.8854 18.0393,20.6793 17.3106,20.1662C16.9605,20.3559 16.5876,20.4952 16.2299,20.6003C15.5742,20.7927 14.8754,20.8968 14.2534,20.9534C13.6801,21.0055 13.4553,21.0037 13.1015,21.0008C13.0689,21.0005 13.0352,21.0002 13,21H12.8594C12.8214,21.0002 12.785,21.0006 12.7504,21.0009C12.6524,21.0019 12.5683,21.0027 12.5,21H12.0562C12.0277,21.0003 12.0054,21.0006 11.9926,21.001L11.9751,21H9L11,19H11.9795C11.9929,18.9997 12.0064,18.9997 12.0199,19H12.4117C12.4534,18.9996 12.4864,18.9995 12.5,19H12.9675C12.977,18.9999 12.9878,18.9999 13,19C13.0446,19.0003 13.0859,19.0007 13.1249,19.0011C13.4259,19.0038 13.591,19.0054 14.0723,18.9616C14.6201,18.9118 15.1795,18.8242 15.6665,18.6813C15.753,18.6559 15.8346,18.6295 15.9114,18.6022C15.0315,17.2981 14.7125,16.1044 15.015,15.0829C15.4095,13.7511 16.6784,13.2418 17.7026,13.2864C18.7262,13.3309 19.954,13.9529 20.1936,15.3369ZM16.9327,15.6508C16.873,15.8523 16.8651,16.3878 17.4697,17.334C18.2007,16.4284 18.2585,15.8839 18.2229,15.6781C18.1939,15.5108 18.0297,15.3025 17.6157,15.2845C17.2025,15.2665 16.9885,15.4626 16.9327,15.6508Z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam.xml b/packages/SystemUI/res/drawable/ic_videocam.xml
new file mode 100644
index 0000000..de2bc7b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_videocam.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M7,40Q5.8,40 4.9,39.1Q4,38.2 4,37V11Q4,9.8 4.9,8.9Q5.8,8 7,8H33Q34.2,8 35.1,8.9Q36,9.8 36,11V21.75L44,13.75V34.25L36,26.25V37Q36,38.2 35.1,39.1Q34.2,40 33,40ZM7,37H33Q33,37 33,37Q33,37 33,37V11Q33,11 33,11Q33,11 33,11H7Q7,11 7,11Q7,11 7,11V37Q7,37 7,37Q7,37 7,37ZM7,37Q7,37 7,37Q7,37 7,37V11Q7,11 7,11Q7,11 7,11Q7,11 7,11Q7,11 7,11V37Q7,37 7,37Q7,37 7,37Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
index 18fcebb..dfb73a9 100644
--- a/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
+++ b/packages/SystemUI/res/drawable/keyguard_bottom_affordance_bg.xml
@@ -27,22 +27,26 @@
android:top="3dp"
android:right="3dp"
android:bottom="3dp">
- <shape android:shape="oval">
+ <!-- We make the shapes a rounded rectangle instead of an oval so that it can animate -->
+ <!-- properly into an app/dialog. -->
+ <shape android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface"/>
<size
- android:width="@dimen/keyguard_affordance_width"
- android:height="@dimen/keyguard_affordance_height"/>
+ android:width="@dimen/keyguard_affordance_fixed_width"
+ android:height="@dimen/keyguard_affordance_fixed_height"/>
+ <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/>
</shape>
</item>
<item>
- <shape android:shape="oval">
+ <shape android:shape="rectangle">
<stroke
android:color="@color/control_primary_text"
android:width="2dp"/>
<size
- android:width="@dimen/keyguard_affordance_width"
- android:height="@dimen/keyguard_affordance_height"/>
+ android:width="@dimen/keyguard_affordance_fixed_width"
+ android:height="@dimen/keyguard_affordance_fixed_height"/>
+ <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/>
</shape>
</item>
</layer-list>
@@ -55,11 +59,12 @@
android:top="3dp"
android:right="3dp"
android:bottom="3dp">
- <shape android:shape="oval">
+ <shape android:shape="rectangle">
<solid android:color="?androidprv:attr/colorSurface"/>
<size
- android:width="@dimen/keyguard_affordance_width"
- android:height="@dimen/keyguard_affordance_height"/>
+ android:width="@dimen/keyguard_affordance_fixed_width"
+ android:height="@dimen/keyguard_affordance_fixed_height"/>
+ <corners android:radius="@dimen/keyguard_affordance_fixed_radius"/>
</shape>
</item>
</layer-list>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 5aa6080..d1a2cf4 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -25,6 +25,7 @@
android:focusable="true"
android:clipChildren="false"
android:clipToPadding="false"
+ android:paddingStart="8dp"
>
<LinearLayout
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index bbb8df1c..db94c92 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -26,6 +26,17 @@
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/unlock_prompt_footer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dp"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center"
+ android:drawablePadding="8dp"
+ android:visibility="gone"
+ android:textAppearance="?android:attr/textAppearanceButton"
+ android:text="@string/unlock_to_see_notif_text"/>
<com.android.systemui.statusbar.notification.row.FooterViewButton
style="@style/TextAppearance.NotificationSectionHeaderButton"
android:id="@+id/manage_text"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 2fd6329..fcef0d2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ondergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Regtergrens <xliff:g id="PERCENT">%1$d</xliff:g> persent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Werkskermskote word in die <xliff:g id="APP">%1$s</xliff:g>-app gestoor"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Lêers"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skermopnemer"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
@@ -384,11 +386,11 @@
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Begin opneem of uitsaai met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Laat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toe om te deel of op te neem?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Hele skerm"</string>
- <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"’n Enkele program"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"’n Enkele app"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Wanneer jy deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
<string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Wanneer jy ’n program deel, opneem of uitsaai, het <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> toegang tot enigiets wat in daardie program sigbaar is of daarin gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Gaan voort"</string>
- <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deel of neem ’n program op"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Deel of neem ’n app op"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Laat hierdie app toe om te deel of op te neem?"</string>
<string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Wanneer jy deel, opneem of uitsaai, het hierdie app toegang tot enigiets wat op jou skerm sigbaar is of op jou toestel gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
<string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Wanneer jy ’n app deel, opneem of uitsaai, het hierdie app toegang tot enigiets wat in daardie program sigbaar is of daarin gespeel word. Wees dus versigtig met wagwoorde, betalingbesonderhede, boodskappe of ander sensitiewe inligting."</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Klein"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Groot"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Maak toe"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Wysig"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Vergrootglasvensterinstellings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tik om toeganklikheidkenmerke oop te maak Pasmaak of vervang knoppie in Instellings.\n\n"<annotation id="link">"Bekyk instellings"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Skuif knoppie na kant om dit tydelik te versteek"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ontdoen"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> kortpad is verwyder"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# kortpad is verwyder}other{# kortpaaie is verwyder}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Beweeg na links bo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Beweeg na regs bo"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Beweeg na links onder"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Speel <xliff:g id="SONG_NAME">%1$s</xliff:g> vanaf <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Ontdoen"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Beweeg nader om op <xliff:g id="DEVICENAME">%1$s</xliff:g> te speel"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Beweeg nader aan <xliff:g id="DEVICENAME">%1$s</xliff:g> om hier te speel"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Speel tans op <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Iets is fout. Probeer weer."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Laai tans"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrole is nie beskikbaar nie"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Luidsprekers en skerms"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Voorgestelde toestelle"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitsaai werk"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Saai uit"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mense in jou omtrek met versoenbare Bluetooth-toestelle kan na die media luister wat jy uitsaai"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Hierdie skerm sal afskakel"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Voubare toestel word ontvou"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Voubare toestel word omgekeer"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stilus se battery is amper pap"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d18bbac..9ae21c1 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"የታች ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"የግራ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"የቀኝ ወሰን <xliff:g id="PERCENT">%1$d</xliff:g> በመቶ"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"የማያ መቅጃ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገጽ ቀረጻን በማሰናዳት ላይ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"መካከለኛ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ትንሽ"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ትልቅ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ዝጋ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"አርትዕ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"የማጉያ መስኮት ቅንብሮች"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"የተደራሽነት ባህሪያትን ለመክፈት መታ ያድርጉ። ይህንን አዝራር በቅንብሮች ውስጥ ያብጁ ወይም ይተኩ።\n\n"<annotation id="link">"ቅንብሮችን አሳይ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ለጊዜው ለመደበቅ አዝራሩን ወደ ጠርዝ ያንቀሳቅሱ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ቀልብስ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> አቋራጭ ተወግዷል"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# አቋራጭ ተወግዷል}one{# አቋራጭ ተወግዷል}other{# አቋራጮች ተወግደዋል}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ወደ ላይኛው ግራ አንቀሳቅስ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ወደ ላይኛው ቀኝ አንቀሳቅስ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"የግርጌውን ግራ አንቀሳቅስ"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ከ<xliff:g id="APP_LABEL">%2$s</xliff:g> ያጫውቱ"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ቀልብስ"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"በ<xliff:g id="DEVICENAME">%1$s</xliff:g> ላይ ለማጫወት ጠጋ ያድርጉ"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"እዚህ ለመጫወት ወደ <xliff:g id="DEVICENAME">%1$s</xliff:g> ቀረብ ይበሉ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"በ<xliff:g id="DEVICENAME">%1$s</xliff:g> ላይ በማጫወት ላይ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"የሆነ ችግር ተፈጥሯል። እንደገና ይሞክሩ።"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"በመጫን ላይ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"አልተገኘም"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"የድምጽ መጠን"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ድምጽ ማውጫዎች እና ማሳያዎች"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ማሰራጨት እንዴት እንደሚሠራ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ስርጭት"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ተኳሃኝ የብሉቱዝ መሣሪያዎች ያላቸው በአቅራቢያዎ ያሉ ሰዎች እርስዎ እያሰራጩት ያሉትን ሚዲያ ማዳመጥ ይችላሉ"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ይህ ማያ ገጽ ይጠፋል"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"መታጠፍ የሚችል መሣሪያ እየተዘረጋ ነው"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"መታጠፍ የሚችል መሣሪያ እየተገለበጠ ነው"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"የብሮስፌ ባትሪ ዝቅተኛ ነው"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index fb267a5..3e160c7 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"الحد السفلى <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"الحد الأيسر <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"الحد الأيمن <xliff:g id="PERCENT">%1$d</xliff:g> في المئة"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"مسجّل الشاشة"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
@@ -382,7 +386,7 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"ستتمكن الخدمة التي تقدّم هذه الوظيفة من الوصول إلى كل المعلومات المرئية لك على الشاشة أو التي يتم تشغيلها على جهازك أثناء التسجيل أو البث. ويشمل ذلك معلومات مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"هل تريد بدء التسجيل أو البث؟"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"هل تريد بدء التسجيل أو الإرسال باستخدام <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>؟"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"هل تريد السماح لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>بالمشاركة أو التسجيل؟"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"هل تريد السماح لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> بالمشاركة أو التسجيل؟"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"الشاشة بالكامل"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"تطبيق واحد"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"أثناء المشاركة أو التسجيل أو البث، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> الوصول إلى كل العناصر المرئية على شاشتك أو التي يتم تشغيلها على جهازك، لذا يُرجى توخي الحذر بشأن كلمات المرور أو تفاصيل الدفع أو الرسائل أو المعلومات الحساسة الأخرى."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"صغير"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"كبير"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"إغلاق"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"تعديل"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"إعدادات نافذة مكبّر الشاشة"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"انقر لفتح ميزات تسهيل الاستخدام. يمكنك تخصيص هذا الزر أو استبداله من الإعدادات.\n\n"<annotation id="link">"عرض الإعدادات"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"يمكنك نقل الزر إلى الحافة لإخفائه مؤقتًا."</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"تراجع"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار <xliff:g id="FEATURE_NAME">%s</xliff:g>."</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{تمت إزالة اختصار واحد.}zero{تمت إزالة # اختصار.}two{تمت إزالة اختصارَين.}few{تمت إزالة # اختصارات.}many{تمت إزالة # اختصارًا.}other{تمت إزالة # اختصار.}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"نقل إلى أعلى يمين الشاشة"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"نقل إلى أعلى يسار الشاشة"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"نقل إلى أسفل يمين الشاشة"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"تشغيل <xliff:g id="SONG_NAME">%1$s</xliff:g> من تطبيق <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"تراجع"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"عليك الاقتراب لتشغيل الوسائط على <xliff:g id="DEVICENAME">%1$s</xliff:g>."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"يُرجى الاقتراب من <xliff:g id="DEVICENAME">%1$s</xliff:g> لتشغيل الوسائط هنا."</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"جارٍ تشغيل الوسائط على <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"حدث خطأ. يُرجى إعادة المحاولة."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"جارٍ التحميل"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"لم يتم العثور عليه."</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"مستوى الصوت"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"مكبّرات الصوت والشاشات"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"كيفية عمل البث"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"البث"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"يمكن للأشخاص القريبين منك الذين لديهم أجهزة متوافقة تتضمّن بلوتوث الاستماع إلى الوسائط التي تبثها."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* سيتم إطفاء هذه الشاشة."</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"جهاز قابل للطي يجري فتحه"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"جهاز قابل للطي يجري قلبه"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"بطارية قلم الشاشة منخفضة"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 694b0d9..7e330d2 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"তলৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাওঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"সোঁফালৰ সীমা <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"মধ্যমীয়া"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"সৰু"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ডাঙৰ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"বন্ধ কৰক"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"সম্পাদনা কৰক"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"বিবৰ্ধকৰ ৱিণ্ড’ৰ ছেটিং"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"সাধ্য সুবিধাসমূহ খুলিবলৈ টিপক। ছেটিঙত এই বুটামটো কাষ্টমাইজ অথবা সলনি কৰক।\n\n"<annotation id="link">"ছেটিং চাওক"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"বুটামটোক সাময়িকভাৱে লুকুৱাবলৈ ইয়াক একেবাৰে কাষলৈ লৈ যাওক"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"আনডু কৰক"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> টা শ্বৰ্টকাট আঁতৰোৱা হ’ল"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}one{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}other{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"শীৰ্ষৰ বাওঁফালে নিয়ক"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"শীৰ্ষৰ সোঁফালে নিয়ক"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"তলৰ বাওঁফালে নিয়ক"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ত <xliff:g id="SONG_NAME">%1$s</xliff:g> গীতটো প্লে’ কৰক"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"আনডু কৰক"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ত প্লে’ কৰিবলৈ ওচৰলৈ যাওক"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ইয়াত খেলিবলৈ <xliff:g id="DEVICENAME">%1$s</xliff:g>ৰ আৰু ওচৰলৈ যাওক"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ত প্লে কৰি থকা হৈছে"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"কিবা ভুল হ’ল। পুনৰ চেষ্টা কৰক।"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ল’ড হৈ আছে"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্টো পৰীক্ষা কৰক"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ভলিউম"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"স্পীকাৰ আৰু ডিছপ্লে’"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"সম্প্ৰচাৰ কৰাটোৱে কেনেকৈ কাম কৰে"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্ৰচাৰ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"সমিল ব্লুটুথ ডিভাইচৰ সৈতে আপোনাৰ নিকটৱৰ্তী স্থানত থকা লোকসকলে আপুনি সম্প্ৰচাৰ কৰা মিডিয়াটো শুনিব পাৰে"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ই স্ক্ৰীনখন অফ হ’ব"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"জপাব পৰা ডিভাইচৰ জাপ খুলি থকা হৈছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"জপাব পৰা ডিভাইচৰ ওলোটাই থকা হৈছে"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ষ্টাইলাছৰ বেটাৰী কম আছে"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 8462c98..192f236 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Aşağı sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sərhəd <xliff:g id="PERCENT">%1$d</xliff:g> faiz"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Ekran Yazıcısı"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Orta"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Kiçik"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Böyük"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Bağlayın"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Redaktə edin"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Böyüdücü pəncərə ayarları"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Əlçatımlılıq funksiyalarını açmaq üçün toxunun. Ayarlarda bu düyməni fərdiləşdirin və ya dəyişdirin.\n\n"<annotation id="link">"Ayarlara baxın"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düyməni müvəqqəti gizlətmək üçün kənara çəkin"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Geri qaytarın"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> qısayol silindi"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# qısayol silindi}other{# qısayol silindi}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuxarıya sola köçürün"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Yuxarıya sağa köçürün"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Aşağıya sola köçürün"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> mahnısını <xliff:g id="APP_LABEL">%2$s</xliff:g> tətbiqindən oxudun"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Geri qaytarın"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oxutmaq üçün yaxınlaşın"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Burada oxutmaq üçün <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaxınlaşın"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oxudulur"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Xəta oldu. Yenə cəhd edin."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Yüklənir"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Səs"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Dinamiklər & Displeylər"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayım necə işləyir"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Yayım"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Uyğun Bluetooth cihazları olan yaxınlığınızdakı insanlar yayımladığınız medianı dinləyə bilər"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran deaktiv ediləcək"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Qatlana bilən cihaz açılır"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Qatlana bilən cihaz fırladılır"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Qələm enerjisi azdır"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 8be7609..ae59e01f 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donja ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Leva ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna ivica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednje"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Malo"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Veliko"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zatvori"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Izmeni"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Podešavanja prozora za uvećanje"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite za funkcije pristupačnosti. Prilagodite ili zamenite ovo dugme u Podešavanjima.\n\n"<annotation id="link">"Podešavanja"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomerite dugme do ivice da biste ga privremeno sakrili"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Opozovi"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Prečica funkcije<xliff:g id="FEATURE_NAME">%s</xliff:g> je uklonjena"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# prečica je uklonjena}one{# prečica je uklonjena}few{# prečice su uklonjene}other{# prečica je uklonjeno}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premesti gore levo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premesti gore desno"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Premesti dole levo"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Opozovi"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite da biste puštali muziku na: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da biste na njemu puštali"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Pušta se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Došlo je do greške. Probajte ponovo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Učitava se"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Zvuk"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i ekrani"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcioniše emitovanje"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Emitovanje"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ljudi u blizini sa kompatibilnim Bluetooth uređajima mogu da slušaju medijski sadržaj koji emitujete"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj ekran će se isključiti"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Uređaj na preklop se otvara"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Uređaj na preklop se obrće"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Nizak nivo baterije pisaljke"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 1707fc8..53f2ff0 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ніжняя граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Левая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Правая граніца: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Запіс экрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Сярэдні"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Дробны"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Вялікі"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Закрыць"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Змяніць"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Налады акна лупы"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Націсніце, каб адкрыць спецыяльныя магчымасці. Рэгулюйце ці замяняйце кнопку ў Наладах.\n\n"<annotation id="link">"Прагляд налад"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Каб часова схаваць кнопку, перамясціце яе на край"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Адрабіць"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Выдалены <xliff:g id="FEATURE_NAME">%s</xliff:g> ярлык"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Выдалены # ярлык}one{Выдалены # ярлык}few{Выдалена # ярлыкі}many{Выдалена # ярлыкоў}other{Выдалена # ярлыка}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перамясціць лявей і вышэй"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перамясціць правей і вышэй"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Перамясціць лявей і ніжэй"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Прайграйце кампазіцыю \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" з дапамогай праграмы \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Адрабіць"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Каб прайграць мультымедыя на прыладзе \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", наблізьцеся да яе"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Падыдзіце бліжэй да прылады \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", каб прайграць на гэтай"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Прайграецца на прыладзе \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\""</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешта пайшло не так. Паўтарыце спробу."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Ідзе загрузка"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знойдзена"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Гучнасць"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Дынамікі і дысплэі"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як адбываецца трансляцыя"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Трансляцыя"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Людзі паблізу, у якіх ёсць прылады з Bluetooth, змогуць праслухваць мультымедыйнае змесціва, якое вы трансліруеце"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Гэты экран будзе выключаны"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складная прылада ў раскладзеным выглядзе"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перавернутая складная прылада"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Нізкі ўзровень зараду пяра"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index e39273b..71fdfa9 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Долна граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лява граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Дясна граница: <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Запис на екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
@@ -386,12 +390,12 @@
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Цял екран"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Едно приложение"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когато споделяте, записвате или предавате, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в това приложение, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Когато споделяте, записвате или предавате приложение, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> има достъп до всичко, което се показва или възпроизвежда в това приложение, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Напред"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Споделяне или записване на приложение"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Да се разреши ли на това приложение да споделя или записва?"</string>
<string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Когато споделяте, записвате или предавате, това приложение има достъп до всичко, което се вижда на екрана ви или се възпроизвежда на устройството ви, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
- <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Когато споделяте, записвате или предавате, това приложение има достъп до всичко, което се показва или възпроизвежда в него, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
+ <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Когато споделяте, записвате или предавате приложение, това приложение има достъп до всичко, което се показва или възпроизвежда в приложението, затова бъдете внимателни с пароли, подробности за начини на плащане, съобщения или друга поверителна информация."</string>
<string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Блокирано от системния ви администратор"</string>
<string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Заснемането на екрана е деактивирано от правило за устройството"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Изчистване на всички"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Среден"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Малък"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Голям"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Затваряне"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Редактиране"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Настройки за инструмента за увеличаване на прозорци"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Докоснете, за да отворите функциите за достъпност. Персон./заменете бутона от настройките.\n\n"<annotation id="link">"Преглед на настройките"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете бутона до края, за да го скриете временно"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Отмяна"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> пряк път бе премахнат"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# пряк път бе премахнат}other{# преки пътя бяха премахнати}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Преместване горе вляво"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Преместване горе вдясно"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Преместване долу вляво"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пускане на <xliff:g id="SONG_NAME">%1$s</xliff:g> от <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Отмяна"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Преместете се по-близо, за да се възпроизведе на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближете се до <xliff:g id="DEVICENAME">%1$s</xliff:g> за възпроизвеждане на това устройство"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Възпроизвежда се на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нещо се обърка. Опитайте отново."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Зарежда се"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Сила на звука"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Високоговорители и екрани"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работи предаването"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Предаване"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Хората в близост със съвместими устройства с Bluetooth могат да слушат мултимедията, която предавате"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Този екран ще се изключи"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Разгъване на сгъваемо устройство"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Обръщане на сгъваемо устройство"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Батерията на писалката е изтощена"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 0159629..9a91787 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"নিচের প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"বাঁ প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> শতাংশ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ডান প্রান্ত থেকে <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"অফিসের স্ক্রিনশট <xliff:g id="APP">%1$s</xliff:g> অ্যাপে সেভ করা হয়"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ফাইল"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"স্ক্রিন রেকর্ডার"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"মাঝারি"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ছোট"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"বড়"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"বন্ধ করুন"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"এডিট করুন"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"\'ম্যাগনিফায়ার উইন্ডো\' সেটিংস"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"অ্যাক্সেসিবিলিটি ফিচার খুলতে ট্যাপ করুন। কাস্টমাইজ করুন বা সেটিংসে এই বোতামটি সরিয়ে দিন।\n\n"<annotation id="link">"সেটিংস দেখুন"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"এটি অস্থায়ীভাবে লুকাতে বোতামটি কোণে সরান"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"আগের অবস্থায় ফিরুন"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-এর শর্টকাট সরানো হয়েছে"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{#টি শর্টকাট সরানো হয়েছে}one{#টি শর্টকাট সরানো হয়েছে}other{#টি শর্টকাট সরানো হয়েছে}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"উপরে বাঁদিকে সরান"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"উপরে ডানদিকে সরান"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"নিচে বাঁদিকে সরান"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%2$s</xliff:g> অ্যাপে চালান"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"আগের অবস্থায় ফিরুন"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>-এ চালাতে আরও কাছে আনুন"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"এখান থেকে চালাতে <xliff:g id="DEVICENAME">%1$s</xliff:g>-এর কাছে নিয়ে যান"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>-এ ভিডিও চালানো হচ্ছে"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"কোনও সমস্যা হয়েছে। আবার চেষ্টা করুন।"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"লোড করা হচ্ছে"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"ট্যাবলেট"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ভলিউম"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"স্পিকার & ডিসপ্লে"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"সাজেস্ট করা ডিভাইস"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ব্রডকাস্ট কীভাবে কাজ করে"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"সম্প্রচার করুন"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"আশপাশে লোকজন যাদের মানানসই ব্লুটুথ ডিভাইস আছে, তারা আপনার ব্রডকাস্ট করা মিডিয়া শুনতে পারবেন"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ এই স্ক্রিন বন্ধ হয়ে যাবে"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ফোল্ড করা যায় এমন ডিভাইস খোলা হচ্ছে"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ফোল্ড করা যায় এমন ডিভাইস উল্টানো হচ্ছে"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"স্টাইলাস ব্যাটারিতে চার্জ কম আছে"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index fd1bcae..ef0f703 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donja granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijeva granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desna granica <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Poslovni snimci ekrana se pohranjuju u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fajlovi"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač ekrana"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednje"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Malo"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Veliko"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zatvori"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Uredi"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Postavke prozora povećala"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite da otvorite funkcije pristupačnosti. Prilagodite ili zamijenite dugme u Postavkama.\n\n"<annotation id="link">"Postavke"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Premjestite dugme do ivice da ga privremeno sakrijete"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Opozovi"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Prečica <xliff:g id="FEATURE_NAME">%s</xliff:g> je uklonjena"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# prečica je uklonjena}one{# prečica je uklonjena}few{# prečice su uklonjene}other{# prečica je uklonjeno}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pomjeranje gore lijevo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pomjeranje gore desno"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Pomjeranje dolje lijevo"</string>
@@ -883,12 +884,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> izvođača <xliff:g id="ARTIST_NAME">%2$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducirajte pjesmu <xliff:g id="SONG_NAME">%1$s</xliff:g> pomoću aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Poništi"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite se da reproducirate na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da na njemu reproducirate"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite da reproducirate na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducira se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nešto nije uredu. Pokušajte ponovo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Učitavanje"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Jačina zvuka"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i ekrani"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako funkcionira emitiranje"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Emitirajte"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u vašoj blizini s kompatibilnim Bluetooth uređajima mogu slušati medijske sadržaje koje emitirate"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ekran će se isključiti"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Sklopivi uređaj se rasklapa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Sklopivi uređaj se obrće"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Baterija pisaljke je slaba"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0d13667..e41292c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Marge inferior <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marge esquerre <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marge dret <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Gravació de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
@@ -98,7 +102,7 @@
<string name="screenrecord_description" msgid="1123231719680353736">"Durant la gravació, el sistema Android pot capturar qualsevol informació sensible que es mostri a la pantalla o que es reprodueixi al dispositiu. Això inclou contrasenyes, informació de pagament, fotos, missatges i àudio."</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Grava la pantalla completa"</string>
<string name="screenrecord_option_single_app" msgid="5954863081500035825">"Grava una sola aplicació"</string>
- <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Mentre graves, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Mentre graves contingut, Android pot accedir a tot el que es veu a la pantalla o que es reprodueix al dispositiu. Per això cal que vagis amb compte amb les contrasenyes, les dades de pagament, els missatges o qualsevol altra informació sensible."</string>
<string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Mentre graves una aplicació, Android té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"Inicia la gravació"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Grava l\'àudio"</string>
@@ -382,11 +386,11 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"El servei que ofereix aquesta funció tindrà accés a tota la informació visible a la teva pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara contrasenyes, detalls dels pagaments, fotos, missatges i àudio que reprodueixis."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vols començar a gravar o emetre contingut?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vols començar a gravar o emetre contingut amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vols permetre que <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comparteixi o gravi?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Vols permetre que <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> comparteixi o gravi contingut?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Tota la pantalla"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Una sola aplicació"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Quan estàs compartint, gravant o emetent, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi al dispositiu. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Quan estàs compartint, gravant o emetent, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> té accés a qualsevol cosa que es vegi a la pantalla o que es reprodueixi a l\'aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges o altra informació sensible."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Mentre comparteixes, graves o emets contingut, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> pot accedir a tot el que es veu a la pantalla o que es reprodueix a l\'aplicació. Per això cal que vagis amb compte amb les contrasenyes, les dades de pagament, els missatges o qualsevol altra informació sensible."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continua"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Comparteix o grava una aplicació"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Vols permetre que aquesta aplicació comparteixi o gravi contingut?"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Normal"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Petit"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Gran"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Tanca"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edita"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configuració de la finestra de la lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca per obrir funcions d\'accessibilitat. Personalitza o substitueix el botó a Configuració.\n\n"<annotation id="link">"Mostra"</annotation>"."</string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mou el botó a l\'extrem per amagar-lo temporalment"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfés"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"S\'ha suprimit la drecera <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{S\'ha suprimit # drecera}many{S\'han suprimit # dreceres}other{S\'han suprimit # dreceres}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mou a dalt a l\'esquerra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mou a dalt a la dreta"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mou a baix a l\'esquerra"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reprodueix <xliff:g id="SONG_NAME">%1$s</xliff:g> des de l\'aplicació <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Desfés"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Mou més a prop per reproduir a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acosta\'t a <xliff:g id="DEVICENAME">%1$s</xliff:g> per reproduir el contingut aquí"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"S\'està reproduint a <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"S\'ha produït un error. Torna-ho a provar."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"S\'està carregant"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altaveus i pantalles"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Com funciona l\'emissió"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Emet"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les persones properes amb dispositius Bluetooth compatibles poden escoltar el contingut multimèdia que emets"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Aquesta pantalla s\'apagarà"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositiu plegable desplegant-se"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositiu plegable girant"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria del llapis òptic baixa"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 11efa36..1bf8f2e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Dolní okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Levý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Pravý okraj <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Střední"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Malý"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Velký"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zavřít"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Upravit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Nastavení okna zvětšení"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Klepnutím otevřete funkce přístupnosti. Tlačítko lze upravit nebo nahradit v Nastavení.\n\n"<annotation id="link">"Nastavení"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Přesunutím tlačítka k okraji ho dočasně skryjete"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Vrátit zpět"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Zkratka <xliff:g id="FEATURE_NAME">%s</xliff:g> byla odstraněna"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Byla odstraněna # zkratka}few{Byly odstraněny # zkratky}many{Bylo odstraněno # zkratky}other{Bylo odstraněno # zkratek}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Přesunout vlevo nahoru"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Přesunout vpravo nahoru"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Přesunout vlevo dolů"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Přehrát skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikace <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Vrátit zpět"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Pokud chcete přehrávat na zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>, přibližte se k němu"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Pokud zde chcete přehrávat média, přibližte se k zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Přehrávání v zařízení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Došlo k chybě. Zkuste to znovu."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Načítání"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hlasitost"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Reproduktory a displeje"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak vysílání funguje"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Vysílání"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lidé ve vašem okolí s kompatibilními zařízeními Bluetooth mohou poslouchat média, která vysíláte"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tato obrazovka se vypne"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozkládání rozkládacího zařízení"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Otáčení rozkládacího zařízení"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Slabá baterie dotykového pera"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 2fbd18e..c560843 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nederste kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Højre kant: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Skærmoptagelse"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mellem"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Lille"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Stor"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Luk"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Rediger"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Indstillinger for lupvindue"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tryk for at åbne hjælpefunktioner. Tilpas eller erstat denne knap i Indstillinger.\n\n"<annotation id="link">"Se indstillingerne"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flyt knappen til kanten for at skjule den midlertidigt"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Fortryd"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Genvejen til <xliff:g id="FEATURE_NAME">%s</xliff:g> er fjernet"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# genvej er fjernet}one{# genvej er fjernet}other{# genveje er fjernet}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flyt op til venstre"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flyt op til højre"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Flyt ned til venstre"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> af <xliff:g id="ARTIST_NAME">%2$s</xliff:g> via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Afspil <xliff:g id="SONG_NAME">%1$s</xliff:g> via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Fortryd"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Flyt enheden tættere på for at afspille på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ryk tættere på <xliff:g id="DEVICENAME">%1$s</xliff:g> for at afspille her"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ryk tættere på for at afspille på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Afspilles på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Noget gik galt. Prøv igen."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Indlæser"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Lydstyrke"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Højttalere og skærme"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Sådan fungerer udsendelser"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Udsendelse"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i nærheden, som har kompatible Bluetooth-enheder, kan lytte til det medie, du udsender"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ *Denne skærm slukkes"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldbar enhed foldes ud"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldbar enhed vendes om"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Lavt batteriniveau på styluspen"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 1c344f6..4013a3d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Unterer Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linker Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechter Rand <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Bildschirmaufzeichnung"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
@@ -98,8 +102,8 @@
<string name="screenrecord_description" msgid="1123231719680353736">"Beim Aufnehmen kann das Android-System vertrauliche Informationen erfassen, die auf deinem Bildschirm angezeigt oder von deinem Gerät wiedergegeben werden. Das können Passwörter, Zahlungsinformationen, Fotos, Nachrichten und Audioinhalte sein."</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"Gesamten Bildschirm aufnehmen"</string>
<string name="screenrecord_option_single_app" msgid="5954863081500035825">"Eine einzelne App aufnehmen"</string>
- <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Während der Aufnahme hat Android Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
- <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Während der Aufnahme einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"Während der Aufnahme hat Android Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"Während der Aufnahme einer App hat Android Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"Aufnahme starten"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Audio aufnehmen"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Audio des Geräts"</string>
@@ -385,13 +389,13 @@
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Zulassen, dass <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Inhalte teilt oder aufnimmt?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Gesamter Bildschirm"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Eine einzelne App"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Beim Teilen, Aufnehmen oder Übertragen hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Beim Teilen, Aufnehmen oder Übertragen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Beim Teilen, Aufnehmen oder Übertragen hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Beim Teilen, Aufnehmen oder Übertragen einer App hat <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Weiter"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"App teilen oder aufnehmen"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Dieser App das Teilen oder Aufnehmen erlauben?"</string>
- <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Beim Teilen, Aufnehmen oder Übertragen hat diese App Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
- <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Beim Teilen, Aufnehmen oder Übertragen einer App hat diese App Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen vorsichtig."</string>
+ <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Beim Teilen, Aufnehmen oder Übertragen hat diese App Zugriff auf alle Inhalte, die auf dem Bildschirm sichtbar sind oder auf dem Gerät wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
+ <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Beim Teilen, Aufnehmen oder Übertragen einer App hat diese App Zugriff auf alle Inhalte, die in dieser App sichtbar sind oder wiedergegeben werden. Sei daher vorsichtig mit Passwörtern, Zahlungsdetails, Nachrichten oder anderen vertraulichen Informationen."</string>
<string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"Vom IT-Administrator blockiert"</string>
<string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Bildschirmaufnahme ist durch die Geräterichtlinien deaktiviert"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Alle löschen"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mittel"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Klein"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Groß"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Schließen"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Bearbeiten"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Einstellungen für das Vergrößerungsfenster"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tippe, um die Bedienungshilfen aufzurufen. Du kannst diese Schaltfläche in den Einstellungen anpassen oder ersetzen.\n\n"<annotation id="link">"Zu den Einstellungen"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Durch Ziehen an den Rand wird die Schaltfläche zeitweise ausgeblendet"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Rückgängig machen"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Verknüpfung für „<xliff:g id="FEATURE_NAME">%s</xliff:g>“ entfernt"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# Verknüpfung entfernt}other{# Verknüpfungen entfernt}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Nach oben links verschieben"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Nach rechts oben verschieben"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Nach unten links verschieben"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergeben"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> über <xliff:g id="APP_LABEL">%2$s</xliff:g> wiedergeben"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Rückgängig machen"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Gehe für die Wiedergabe näher an <xliff:g id="DEVICENAME">%1$s</xliff:g> heran"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Platziere für die Wiedergabe dein Gerät näher an „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
- <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Wird auf „<xliff:g id="DEVICENAME">%1$s</xliff:g>“ abgespielt"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Gehe für die Wiedergabe näher an „<xliff:g id="DEVICENAME">%1$s</xliff:g>“ heran"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
+ <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Wiedergabe läuft auf „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Es gab ein Problem. Versuch es noch einmal."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Wird geladen"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Lautstärke"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Lautsprecher & Displays"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Funktionsweise von Nachrichten an alle"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Nachricht an alle"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personen, die in der Nähe sind und kompatible Bluetooth-Geräten haben, können sich die Medien anhören, die du per Nachricht an alle sendest"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dieses Display wird dann ausgeschaltet"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Faltbares Gerät wird geöffnet"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Faltbares Gerät wird umgeklappt"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus-Akkustand niedrig"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 9447fd2..c1188ed 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Κάτω όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Αριστερό όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Δεξί όριο <xliff:g id="PERCENT">%1$d</xliff:g> τοις εκατό"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Τα στιγμιότυπα οθόνης εργασίας αποθηκεύονται στην εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Αρχεία"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Εγγραφή οθόνης"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Μέτριο"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Μικρό"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Μεγάλο"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Κλείσιμο"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Επεξεργασία"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Ρυθμίσεις παραθύρου μεγεθυντικού φακού"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Πατήστε για άνοιγμα των λειτουργιών προσβασιμότητας. Προσαρμόστε ή αντικαταστήστε το κουμπί στις Ρυθμίσεις.\n\n"<annotation id="link">"Προβολή ρυθμίσεων"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Μετακινήστε το κουμπί στο άκρο για προσωρινή απόκρυψη"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Αναίρεση"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Η συντόμευση <xliff:g id="FEATURE_NAME">%s</xliff:g> καταργήθηκε"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Καταργήθηκε # συντόμευση}other{Καταργήθηκαν # συντομεύσεις}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Μετακίνηση επάνω αριστερά"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Μετακίνηση επάνω δεξιά"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Μετακίνηση κάτω αριστερά"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Αναπαραγωγή του <xliff:g id="SONG_NAME">%1$s</xliff:g> στην εφαρμογή <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Αναίρεση"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Πλησιάστε για αναπαραγωγή στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Μετακινηθείτε πιο κοντά στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g> για αναπαραγωγή εδώ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Αναπαραγωγή στη συσκευή <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Παρουσιάστηκε κάποιο πρόβλημα. Δοκιμάστε ξανά."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Φόρτωση"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ένταση ήχου"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Ηχεία και οθόνες"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Προτεινόμενες συσκευές"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Πώς λειτουργεί η μετάδοση"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Μετάδοση"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Οι άνθρωποι με συμβατές συσκευές Bluetooth που βρίσκονται κοντά σας μπορούν να ακούσουν το μέσο που μεταδίδετε."</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Αυτή η οθόνη θα απενεργοποιηθεί"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Αναδιπλούμενη συσκευή που ξεδιπλώνει"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Αναδιπλούμενη συσκευή που διπλώνει"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Χαμηλή στάθμη μπαταρίας γραφίδας"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 982008c..dc4eecc 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -810,7 +812,8 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Small"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Large"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Close"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Magnifier window settings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
@@ -882,10 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Loading"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
@@ -909,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers & displays"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1050,5 +1056,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index fbcff48..3fa3fa7 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -810,7 +812,8 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Small"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Large"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Close"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Magnifier window settings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customize or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
@@ -882,10 +885,11 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
+ <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Loading"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
@@ -909,6 +913,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers & Displays"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested Devices"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting"</string>
@@ -1050,5 +1055,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 982008c..dc4eecc 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -810,7 +812,8 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Small"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Large"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Close"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Magnifier window settings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
@@ -882,10 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Loading"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
@@ -909,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers & displays"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1050,5 +1056,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 982008c..dc4eecc 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -810,7 +812,8 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Small"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Large"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Close"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Magnifier window settings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string>
@@ -882,10 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Loading"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
@@ -909,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers & displays"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested devices"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media that you\'re broadcasting"</string>
@@ -1050,5 +1056,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ This screen will turn off"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 8304f30..0a3cf41 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Work screenshots are saved in the <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -810,7 +812,8 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medium"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Small"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Large"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Close"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Magnifier window settings"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customize or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation>""</string>
@@ -882,10 +885,11 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Play <xliff:g id="SONG_NAME">%1$s</xliff:g> from <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Move closer to play on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g> to play here"</string>
+ <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"To play here, move closer to <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Playing on <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Something went wrong. Try again."</string>
<string name="media_transfer_loading" msgid="5544017127027152422">"Loading"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
@@ -909,6 +913,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers & Displays"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Suggested Devices"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"How broadcasting works"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"People near you with compatible Bluetooth devices can listen to the media you\'re broadcasting"</string>
@@ -1050,5 +1055,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930">""<b>"✱ This screen will turn off"</b>""</string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Foldable device being unfolded"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Foldable device being flipped around"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stylus battery low"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> battery remaining"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Connect your stylus to a charger"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6c9f047..8af2620 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Límite inferior: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Límite izquierdo: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Límite derecho: <xliff:g id="PERCENT">%1$d</xliff:g> por ciento"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Grabadora de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
@@ -386,7 +390,7 @@
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Pantalla completa"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Una sola app"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Cuando compartas, grabes o transmitas contenido, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo aquel que sea visible en la pantalla o que reproduzcas en el dispositivo. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes y otra información sensible."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cuando compartas, grabes o transmitas una app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo el contenido que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes y otra información sensible."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Cuando compartas, grabes o transmitas una app, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> podrá acceder a todo el contenido que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con las contraseñas, los detalles de pagos, los mensajes y otra información sensible."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Continuar"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Compartir o grabar una app"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"¿Quieres permitir que esta app comparta o grabe tu pantalla?"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeño"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Cerrar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configuración de la ventana de ampliación"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Presiona para abrir las funciones de accesibilidad. Personaliza o cambia botón en Config.\n\n"<annotation id="link">"Ver config"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Deshacer"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Se quitó el acceso directo <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Se quitó # acceso directo}many{Se quitaron # accesos directos}other{Se quitaron # accesos directos}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba a la derecha"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover abajo a la izquierda"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproducir <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Deshacer"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Acércate para reproducir en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproducir aquí"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproduciendo en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Se produjo un error. Vuelve a intentarlo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Bocinas y pantallas"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la transmisión"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmisión"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que transmites"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable siendo desplegado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable siendo girado"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"La pluma stylus tiene poca batería"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 44c94be..4437160 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite inferior"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite izquierdo"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> por ciento del límite derecho"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Grabación de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeño"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Cerrar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configuración de la ventana de la lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca para abrir funciones de accesibilidad. Personaliza o sustituye este botón en Ajustes.\n\n"<annotation id="link">"Ver ajustes"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Deshacer"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Acceso directo de <xliff:g id="FEATURE_NAME">%s</xliff:g> eliminado"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# acceso directo eliminado}many{# accesos directos eliminados}other{# accesos directos eliminados}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover arriba a la derecha"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover abajo a la izquierda"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> de <xliff:g id="ARTIST_NAME">%2$s</xliff:g> en <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Poner <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Deshacer"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para que se reproduzca en ese dispositivo"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para jugar aquí"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Acércate a <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproducir contenido ahí"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproduciendo en <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Se ha producido un error. Inténtalo de nuevo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumen"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altavoces y pantallas"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cómo funciona la emisión"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Emisión"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Las personas cercanas con dispositivos Bluetooth compatibles pueden escuchar el contenido multimedia que emites"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta pantalla se apagará"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo plegable desplegándose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo plegable mostrado desde varios ángulos"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Batería del lápiz óptico baja"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 0a71eee..3b6a0af 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alapiir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasak piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Parem piir: <xliff:g id="PERCENT">%1$d</xliff:g> protsenti"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Ekraanisalvesti"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Keskmine"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Väike"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Suur"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Sule"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Muuda"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Luubi akna seaded"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Puudutage juurdepääsufunktsioonide avamiseks. Kohandage nuppu või asendage see seadetes.\n\n"<annotation id="link">"Kuva seaded"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Teisaldage nupp serva, et see ajutiselt peita"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Võta tagasi"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Funktsiooni <xliff:g id="FEATURE_NAME">%s</xliff:g> otsetee eemaldati"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# otsetee eemaldati}other{# otseteed eemaldati}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Teisalda üles vasakule"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Teisalda üles paremale"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Teisalda alla vasakule"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> esitajalt <xliff:g id="ARTIST_NAME">%2$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Esita lugu <xliff:g id="SONG_NAME">%1$s</xliff:g> rakenduses <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Võta tagasi"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Teisaldage lähemale, et seadmes <xliff:g id="DEVICENAME">%1$s</xliff:g> esitada"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Siin esitamiseks liigutage seadmele <xliff:g id="DEVICENAME">%1$s</xliff:g> lähemale"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Liikuge lähemale, et seadmes <xliff:g id="DEVICENAME">%1$s</xliff:g> esitada"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Esitatakse seadmes <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Midagi läks valesti. Proovige uuesti."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Laadimine"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Helitugevus"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Kõlarid ja ekraanid"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kuidas ülekandmine toimib?"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Ülekanne"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Teie läheduses olevad inimesed, kellel on ühilduvad Bluetooth-seadmed, saavad kuulata teie ülekantavat meediat"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ See ekraan lülitatakse välja"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Volditava seadme lahtivoltimine"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Volditava seadme ümberpööramine"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Elektronpliiatsi akutase on madal"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 860d0e3..783a157 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Beheko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ezkerreko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Eskuineko ertza: ehuneko <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Pantaila-grabagailua"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
@@ -701,7 +705,7 @@
<string name="tuner_lock_screen" msgid="2267383813241144544">"Pantaila blokeatua"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"Beroegi egoteagatik itzali da"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"Ohi bezala ari da funtzionatzen telefonoa orain.\nInformazio gehiago lortzeko, sakatu hau."</string>
- <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonoa gehiegi berotu da, eta itzali egin da tenperatura jaisteko. Orain, ohiko moduan dabil.\n\nBerotzearen zergati posibleak:\n • Baliabide asko behar dituzten aplikazioak erabiltzea (adib., jokoak, bideoak edo nabigazio-aplikazioak).\n • Fitxategi handiak deskargatu edo kargatzea.\n • Telefonoa giro beroetan erabiltzea."</string>
+ <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Telefonoa gehiegi berotu da, eta itzali egin da tenperatura jaisteko. Orain, ohiko moduan dabil.\n\nBerotzearen zergati posibleak:\n • Baliabide asko behar dituzten aplikazioak erabiltzea (adib., bideojokoak, bideoak edo nabigazio-aplikazioak).\n • Fitxategi handiak deskargatu edo kargatzea.\n • Telefonoa giro beroetan erabiltzea."</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ikusi zaintzeko urratsak"</string>
<string name="high_temp_title" msgid="2218333576838496100">"Berotzen ari da telefonoa"</string>
<string name="high_temp_notif_message" msgid="1277346543068257549">"Eginbide batzuk ezingo dira erabili telefonoa hoztu arte.\nInformazio gehiago lortzeko, sakatu hau."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Ertaina"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Txikia"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Handia"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Itxi"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editatu"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Luparen leihoaren ezarpenak"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Erabilerraztasun-eginbideak irekitzeko, sakatu hau. Ezarpenetan pertsonalizatu edo ordez dezakezu botoia.\n\n"<annotation id="link">"Ikusi ezarpenak"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Eraman botoia ertzera aldi baterako ezkutatzeko"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desegin"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> eginbidearen lasterbidea kendu da"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# lasterbide kendu da}other{# lasterbide kendu dira}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Eraman goialdera, ezkerretara"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Eraman goialdera, eskuinetara"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Eraman behealdera, ezkerretara"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Erreproduzitu <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> bidez"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Desegin"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Gertura ezazu <xliff:g id="DEVICENAME">%1$s</xliff:g> gailuan erreproduzitzeko"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Gerturatu <xliff:g id="DEVICENAME">%1$s</xliff:g> gailura bertan erreproduzitzen ari dena hemen erreproduzitzeko"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> gailuan erreproduzitzen"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Arazoren bat izan da. Saiatu berriro."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Kargatzen"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Bolumena"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%% <xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Bozgorailuak eta pantailak"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Nola funtzionatzen dute iragarpenek?"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Iragarri"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth bidezko gailu bateragarriak dituzten inguruko pertsonek iragartzen ari zaren multimedia-edukia entzun dezakete"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Pantaila itzali egingo da"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Gailu tolesgarria zabaltzen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Gailu tolesgarria biratzen"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Arkatzak bateria gutxi du"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 19a8f05..df99cdf 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"مرز پایین <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"مرز سمت چپ <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"مرز سمت راست <xliff:g id="PERCENT">%1$d</xliff:g> درصد"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ضبطکننده صفحهنمایش"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحهنمایش"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحهنمایش"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"کوچک"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"بزرگ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"بستن"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ویرایش"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"تنظیمات پنجره ذرهبین"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"برای باز کردن ویژگیهای دسترسپذیری ضربه بزنید. در تنظیمات این دکمه را سفارشی یا جایگزین کنید\n\n"<annotation id="link">"تنظیمات"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"برای پنهان کردن موقتی دکمه، آن را به لبه ببرید"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"واگرد"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> میانبر برداشته شد"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# میانبر برداشته شد}one{# میانبر برداشته شد}other{# میانبر برداشته شد}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"انتقال به بالا سمت راست"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"انتقال به بالا سمت چپ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"انتقال به پایین سمت راست"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%2$s</xliff:g> پخش کنید"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"واگرد"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"برای پخش در <xliff:g id="DEVICENAME">%1$s</xliff:g> به دستگاه نزدیکتر شوید"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"برای پخش در اینجا، به <xliff:g id="DEVICENAME">%1$s</xliff:g> نزدیکتر شوید"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"درحال پخش در <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"مشکلی پیش آمد. دوباره امتحان کنید."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"درحال بار کردن"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"میزان صدا"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"بلندگوها و نمایشگرها"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"همهفرتستی چطور کار میکند"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"همهفرستی"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"افرادی که در اطرافتان دستگاههای Bluetooth سازگار دارند میتوانند به رسانهای که همهفرستی میکنید گوش کنند"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ این صفحهنمایش خاموش خواهد شد"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"دستگاه تاشو درحال باز شدن"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"دستگاه تاشو درحال چرخش به اطراف"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"باتری قلم ضعیف است"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 5b90e57..879508c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alareuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vasen reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oikea reuna <xliff:g id="PERCENT">%1$d</xliff:g> prosenttia"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Näytön tallentaja"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Keskitaso"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pieni"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Suuri"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Sulje"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Muokkaa"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Ikkunan suurennuksen asetukset"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Avaa esteettömyysominaisuudet napauttamalla. Yksilöi tai vaihda painike asetuksista.\n\n"<annotation id="link">"Avaa asetukset"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Piilota painike tilapäisesti siirtämällä se reunaan"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Kumoa"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> pikanäppäin poistettu"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pikanäppäin poistettu}other{# pikanäppäintä poistettu}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Siirrä vasempaan yläreunaan"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Siirrä oikeaan yläreunaan"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Siirrä vasempaan alareunaan"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="APP_LABEL">%2$s</xliff:g>)"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Kumoa"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Siirry lähemmäs, jotta <xliff:g id="DEVICENAME">%1$s</xliff:g> voi toistaa tämän"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Siirrä <xliff:g id="DEVICENAME">%1$s</xliff:g> lähemmäs toistaaksesi täällä"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Toistetaan: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Jotain meni pieleen. Yritä uudelleen."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Latautuminen"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ei löydy"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Äänenvoimakkuus"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Kaiuttimet ja näytöt"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Miten lähetys toimii"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Lähetys"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Lähistöllä olevat ihmiset, joilla on yhteensopiva Bluetooth-laite, voivat kuunnella lähettämääsi mediaa"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Tämä näyttö sammutetaan"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Taitettava laite taitetaan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Taitettava laite käännetään ympäri"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Näyttökynän akku vähissä"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index f4d7816..39ab915 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inférieure : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Moyenne"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Petite"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Fermer"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Modifier"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Paramètres de la fenêtre de loupe"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Touchez pour ouvrir fonction. d\'access. Personnalisez ou remplacez bouton dans Param.\n\n"<annotation id="link">"Afficher param."</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacez le bouton vers le bord pour le masquer temporairement"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Annuler"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Le raccourci <xliff:g id="FEATURE_NAME">%s</xliff:g> a été retiré"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# raccourci retiré}one{# raccourci retiré}many{# de raccourcis retirés}other{# raccourcis retirés}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer dans coin sup. gauche"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Déplacer dans coin sup. droit"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Déplacer dans coin inf. gauche"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Lecture de <xliff:g id="SONG_NAME">%1$s</xliff:g> à partir de <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Annuler"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Rapprochez-vous pour faire jouer le contenu sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Rapprochez-vous de <xliff:g id="DEVICENAME">%1$s</xliff:g> pour lire le contenu"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lecture sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Un problème est survenu. Réessayez."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Chargement en cours…"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Haut-parleurs et écrans"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement de la diffusion"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Diffusion"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité disposant d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Cet écran va s\'éteindre"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable en cours de dépliage"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable en train d\'être retourné"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Pile du stylet faible"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d61bd4c..a8e0cb4 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inférieure : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite gauche : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite droite : <xliff:g id="PERCENT">%1$d</xliff:g> pour cent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Enregistreur d\'écran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Moyen"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Petit"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grand"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Fermer"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Modifier"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Paramètres de la fenêtre d\'agrandissement"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Appuyez pour ouvrir fonctionnalités d\'accessibilité. Personnalisez ou remplacez bouton dans paramètres.\n\n"<annotation id="link">"Voir paramètres"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacer le bouton vers le bord pour le masquer temporairement"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Annuler"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Raccourci <xliff:g id="FEATURE_NAME">%s</xliff:g> supprimé"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# raccourci supprimé}one{# raccourci supprimé}many{# raccourcis supprimés}other{# raccourcis supprimés}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer en haut à gauche"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Déplacer en haut à droite"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Déplacer en bas à gauche"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> depuis <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Annuler"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Rapprochez-vous pour lire sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Rapprochez l\'appareil pour transférer la diffusion à votre <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lecture sur <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Rapprochez-vous de votre <xliff:g id="DEVICENAME">%1$s</xliff:g> pour y lire le contenu"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
+ <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lecture sur <xliff:g id="DEVICENAME">%1$s</xliff:g>…"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Un problème est survenu. Réessayez."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Chargement…"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Enceintes et écrans"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Cet écran sera désactivé"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Appareil pliable qui est déplié"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Appareil pliable qui est retourné"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"La batterie du stylet est faible"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index dbb0387..e180f60 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bordo inferior: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bordo esquerdo: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Bordo dereito: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Gravadora da pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
@@ -394,7 +398,7 @@
<string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Cando compartes, gravas ou emites aplicacións, esta aplicación ten acceso a todo o que se vexa ou se reproduza nelas. Polo tanto, debes ter coidado cos contrasinais, os detalles de pago, as mensaxes ou outra información confidencial."</string>
<string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"O teu administrador de TI bloqueou esta aplicación"</string>
<string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"A política do dispositivo desactivou a opción de capturar a pantalla"</string>
- <string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todas"</string>
+ <string name="clear_all_notifications_text" msgid="348312370303046130">"Eliminar todo"</string>
<string name="manage_notifications_text" msgid="6885645344647733116">"Xestionar"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"Historial"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"Notificacións novas"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediano"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeno"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Pechar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configuración da ventá da lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca para abrir as funcións de accesibilidade. Cambia este botón en Configuración.\n\n"<annotation id="link">"Ver configuración"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Para ocultar temporalmente o botón, móveo ata o bordo"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfacer"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Quitouse o atallo de <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Quitouse # atallo}other{Quitáronse # atallos}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover á parte super. esquerda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover á parte superior dereita"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover á parte infer. esquerda"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduce <xliff:g id="SONG_NAME">%1$s</xliff:g> en <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Desfacer"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Achega o dispositivo para reproducir o contido en: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Achégate ao dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>) para reproducir o contido neste"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducindo contido noutro dispositivo (<xliff:g id="DEVICENAME">%1$s</xliff:g>)"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Produciuse un erro. Téntao de novo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Cargando"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altofalantes e pantallas"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funcionan as difusións?"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Difusión"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As persoas que estean preto de ti e que dispoñan de dispositivos Bluetooth compatibles poden escoitar o contido multimedia que difundas"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Desactivarase esta pantalla"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pregable abríndose"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pregable xirando"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"O lapis óptico ten pouca batería"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 5701595..d866a96 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"નીચેની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ડાબી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"જમણી બાજુની સીમા <xliff:g id="PERCENT">%1$d</xliff:g> ટકા"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"સ્ક્રીન રેકોર્ડર"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"મધ્યમ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"નાનું"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"મોટું"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"બંધ કરો"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ફેરફાર કરો"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"મેગ્નિફાયર વિન્ડોના સેટિંગ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ઍક્સેસિબિલિટી સુવિધાઓ ખોલવા માટે ટૅપ કરો. સેટિંગમાં આ બટનને કસ્ટમાઇઝ કરો અથવા બદલો.\n\n"<annotation id="link">"સેટિંગ જુઓ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"તેને હંગામી રૂપે ખસેડવા માટે બટનને કિનારી પર ખસેડો"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"છેલ્લો ફેરફાર રદ કરો"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> શૉર્ટકટ કાઢી નાખ્યો"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# શૉર્ટકટ કાઢી નાખ્યો}one{# શૉર્ટકટ કાઢી નાખ્યો}other{# શૉર્ટકટ કાઢી નાખ્યા}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ઉપર ડાબે ખસેડો"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ઉપર જમણે ખસેડો"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"નીચે ડાબે ખસેડો"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> પર <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"છેલ્લો ફેરફાર રદ કરો"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> પર ચલાવવા માટે વધુ નજીક ખસેડો"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"આમાં ચલાવવા માટે ડિવાઇસને <xliff:g id="DEVICENAME">%1$s</xliff:g>ની નજીક ખસેડો"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> પર ચલાવવામાં આવી રહ્યું છે"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"કંઈક ખોટું થયું. ફરી પ્રયાસ કરો."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"લોડ થઈ રહ્યું છે"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"મળ્યું નથી"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"વૉલ્યૂમ"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"સ્પીકર અને ડિસ્પ્લે"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"બ્રોડકાસ્ટ પ્રક્રિયાની કામ કરવાની રીત"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"બ્રોડકાસ્ટ કરો"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"સુસંગત બ્લૂટૂથ ડિવાઇસ ધરાવતા નજીકના લોકો તમે જે મીડિયા બ્રોડકાસ્ટ કરી રહ્યાં છો તે સાંભળી શકે છે"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ આ સ્ક્રીન બંધ થઈ જશે"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ અનફોલ્ડ કરવામાં આવી રહ્યું છે"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ફોલ્ડ કરી શકાય એવું ડિવાઇસ ફ્લિપ કરવામાં આવી રહ્યું છે"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"સ્ટાઇલસની બૅટરીમાં ચાર્જ ઓછો છે"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index dfa1192..330b6f1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"निचले किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दाएं किनारे से <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रिकॉर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
@@ -382,11 +386,11 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"इस फ़ंक्शन को उपलब्ध कराने वाली सेवा, रिकॉर्ड या कास्ट करते समय, आपकी स्क्रीन पर दिखने वाली या चलाई जाने वाली जानकारी को ऐक्सेस कर सकती है. इसमें पासवर्ड, पैसे चुकाने से जुड़ी जानकारी, फ़ोटो, मैसेज, और चलाए जाने वाले ऑडियो शामिल हैं."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"रिकॉर्डिंग या कास्ट करना शुरू करें?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> का इस्तेमाल करके रिकॉर्ड और कास्ट करना शुरू करें?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> को शेयर या रिकॉर्ड करने की अनुमति दें?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"क्या आपको शेयर या रिकॉर्ड करने की <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> को अनुमति देनी है?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"पूरी स्क्रीन"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"सिर्फ़ एक ऐप्लिकेशन"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास स्क्रीन पर दिख रही हर चीज़ या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रही हर चीज़ या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, शेयर, रिकॉर्ड या कास्ट करते समय, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"शेयर, रिकॉर्ड या कास्ट करते समय, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> के पास उस ऐप्लिकेशन पर दिख रही हर चीज़ या उस पर चल रहे हर मीडिया का ऐक्सेस होता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज या किसी और संवेदनशील जानकारी को लेकर खास सावधानी बरतें."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"जारी रखें"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"क्या इस ऐप्लिकेशन को शेयर या रिकॉर्ड करने की अनुमति देनी है?"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्यम"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"छोटा"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"बड़ा"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"बंद करें"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"बदलाव करें"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ज़ूम करने की सुविधा वाली विंडो से जुड़ी सेटिंग"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"सुलभता सुविधाएं खोलने के लिए टैप करें. सेटिंग में, इस बटन को बदलें या अपने हिसाब से सेट करें.\n\n"<annotation id="link">"सेटिंग देखें"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटन को कुछ समय छिपाने के लिए, उसे किनारे पर ले जाएं"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"पहले जैसा करें"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> का शॉर्टकट हटाया गया"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# शॉर्टकट हटाया गया}one{# शॉर्टकट हटाया गया}other{# शॉर्टकट हटाए गए}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सबसे ऊपर बाईं ओर ले जाएं"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सबसे ऊपर दाईं ओर ले जाएं"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"सबसे नीचे बाईं ओर ले जाएं"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> पर, <xliff:g id="SONG_NAME">%1$s</xliff:g> चलाएं"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"पहले जैसा करें"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> पर मीडिया चलाने के लिए, अपने डिवाइस को उसके पास ले जाएं"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"अपने डिवाइस पर मीडिया फ़ाइल ट्रांसफ़र करने के लिए, उसे <xliff:g id="DEVICENAME">%1$s</xliff:g> के पास ले जाएं"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> पर मीडिया चल रहा है"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"कोई गड़बड़ी हुई. फिर से कोशिश करें."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"लोड हो रहा है"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं है"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"वॉल्यूम"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"स्पीकर और डिसप्ले"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्ट करने की सुविधा कैसे काम करती है"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करें"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"आपके आस-पास मौजूद लोग, ब्रॉडकास्ट किए जा रहे मीडिया को सुन सकते हैं. हालांकि, इसके लिए उनके पास ऐसे ब्लूटूथ डिवाइस होने चाहिए जिन पर मीडिया चलाया जा सके"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यह स्क्रीन बंद हो जाएगी"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फ़ोल्ड किया जा सकने वाला डिवाइस अनफ़ोल्ड किया जा रहा है"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फ़ोल्ड किया जा सकने वाला डिवाइस पलटा जा रहा है"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"स्टाइलस की बैटरी कम है"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 36908e5..c15fabf 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Donji rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Lijevi rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Desni rub <xliff:g id="PERCENT">%1$d</xliff:g> posto"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Snimke zaslona s poslovnog profila spremaju se u aplikaciju <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Datoteke"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Snimač zaslona"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string>
@@ -388,7 +390,7 @@
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Kad dijelite, snimate ili emitirate, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što je vidljivo na vašem zaslonu ili se reproducira na vašem uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
<string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Kad dijelite, snimate ili emitirate aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Nastavi"</string>
- <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dijeljenje ili snimanje pomoću aplikacije"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Dijeljenje ili snimanje aplikacije"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Želite li ovoj aplikaciji omogućiti dijeljenje ili bilježenje?"</string>
<string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Kad dijelite, snimate ili emitirate, ova aplikacija ima pristup svemu što je vidljivo na vašem zaslonu ili se reproducira na vašem uređaju. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
<string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Kad dijelite, snimate ili emitirate aplikaciju, ova aplikacija ima pristup svemu što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na zaporke, podatke o plaćanju, poruke i druge osjetljive podatke."</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednja"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Mala"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Velika"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zatvori"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Uredi"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Postavke prozora povećala"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite za otvaranje značajki pristupačnosti. Prilagodite ili zamijenite taj gumb u postavkama.\n\n"<annotation id="link">"Pregledajte postavke"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomaknite gumb do ruba da biste ga privremeno sakrili"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Poništi"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Uklonjen je prečac za <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Uklonjen je # prečac}one{Uklonjen je # prečac}few{Uklonjena su # prečaca}other{Uklonjeno je # prečaca}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premjesti u gornji lijevi kut"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premjesti u gornji desni kut"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Premjesti u donji lijevi kut"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Pustite <xliff:g id="SONG_NAME">%1$s</xliff:g> putem aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Poništi"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Približite se radi reprodukcije na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približite se uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g> da biste na njemu reproducirali"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Reproducira se na uređaju <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nešto nije u redu. Pokušajte ponovo."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Učitavanje"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Glasnoća"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvučnici i zasloni"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Predloženi uređaji"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako emitiranje funkcionira"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Emitiranje"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osobe u blizini s kompatibilnim Bluetooth uređajima mogu slušati medije koje emitirate"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ovaj će se zaslon isključiti"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rasklopljen sklopivi uređaj"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Okretanje sklopivog uređaja sa svih strana"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Slaba baterija pisaljke"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index aeb7ec4..39deae7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alsó rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Bal oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Jobb oldali rész <xliff:g id="PERCENT">%1$d</xliff:g> százaléka"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Képernyőrögzítő"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Közepes"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Kicsi"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Nagy"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Bezárás"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Szerkesztés"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Nagyítóablak beállításai"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Koppintson a kisegítő lehetőségek megnyitásához. A gombot a Beállításokban módosíthatja.\n\n"<annotation id="link">"Beállítások"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"A gombot a szélre áthelyezve ideiglenesen elrejtheti"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Visszavonás"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> gyorsparancs eltávolítva"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# gyorsparancs eltávolítva}other{# gyorsparancs eltávolítva}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Áthelyezés fel és balra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Áthelyezés fel és jobbra"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Áthelyezés le és balra"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> <xliff:g id="SONG_NAME">%1$s</xliff:g> című számának lejátszása innen: <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> lejátszása innen: <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Visszavonás"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Menjen közelebb a következőn való lejátszáshoz: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Menjen közelebb a(z) <xliff:g id="DEVICENAME">%1$s</xliff:g> eszközhöz, hogy itt játszhassa le a tartalmat"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Menjen közelebb, ha itt szeretné lejátszani: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Lejátszás folyamatban a(z) <xliff:g id="DEVICENAME">%1$s</xliff:g> eszközön"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Hiba történt. Próbálkozzon újra."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Betöltés…"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hangerő"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hangfalak és kijelzők"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"A közvetítés működése"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Közvetítés"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"A közelben tartózkodó, kompatibilis Bluetooth-eszközzel rendelkező személyek meghallgathatják az Ön közvetített médiatartalmait"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ A képernyő kikapcsol"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Összehajtható eszköz kihajtása"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Összehajtható eszköz körbeforgatása"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Az érintőceruza töltöttsége alacsony"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4910867..f2e10d4 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ներքևի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Ձախ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Աջ կողմի սահմանագիծը՝ <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Էկրանի տեսագրիչ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Միջին"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Փոքր"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Մեծ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Փակել"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Փոփոխել"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Խոշորացույցի պատուհանի կարգավորումներ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Հատուկ գործառույթները բացելու համար հպեք։ Անհատականացրեք այս կոճակը կարգավորումներում։\n\n"<annotation id="link">"Կարգավորումներ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Կոճակը ժամանակավորապես թաքցնելու համար այն տեղափոխեք էկրանի եզր"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Հետարկել"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"«<xliff:g id="FEATURE_NAME">%s</xliff:g>» դյուրանցումը հեռացվեց"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# դյուրանցում հեռացվեց}one{# դյուրանցում հեռացվեց}other{# դյուրանցում հեռացվեց}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Տեղափոխել վերև՝ ձախ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Տեղափոխել վերև՝ աջ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Տեղափոխել ներքև՝ ձախ"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Նվագարկել <xliff:g id="SONG_NAME">%1$s</xliff:g> երգը <xliff:g id="APP_LABEL">%2$s</xliff:g> հավելվածից"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Հետարկել"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ավելի մոտ եկեք՝ <xliff:g id="DEVICENAME">%1$s</xliff:g> սարքում նվագարկելու համար"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ավելի մոտեցեք «<xliff:g id="DEVICENAME">%1$s</xliff:g>» սարքին՝ նվագարկումը սկսելու համար"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Նվագարկվում է «<xliff:g id="DEVICENAME">%1$s</xliff:g>» սարքում"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Բեռնվում է"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Չի գտնվել"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ձայնի ուժգնություն"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Բարձրախոսներ և էկրաններ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ինչպես է աշխատում հեռարձակումը"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Հեռարձակում"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ձեր մոտակայքում գտնվող՝ համատեղելի Bluetooth սարքերով մարդիկ կարող են լսել մեդիա ֆայլերը, որոնք դուք հեռարձակում եք։"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Այս էկրանը կանջատվի"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ծալովի սարք՝ բացված վիճակում"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Ծալովի սարք՝ շրջված վիճակում"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Ստիլուսի մարտկոցի լիցքի ցածր մակարդակ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index cf76529..93ac4fe 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Batas bawah <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Batas kiri <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Batas kanan <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Perekam Layar"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Sedang"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Kecil"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Besar"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Tutup"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Setelan jendela kaca pembesar"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ketuk untuk membuka fitur aksesibilitas. Sesuaikan atau ganti tombol ini di Setelan.\n\n"<annotation id="link">"Lihat setelan"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pindahkan tombol ke tepi agar tersembunyi untuk sementara"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Urungkan"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pintasan <xliff:g id="FEATURE_NAME">%s</xliff:g> dihapus"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pintasan dihapus}other{# pintasan dihapus}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pindahkan ke kiri atas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pindahkan ke kanan atas"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Pindahkan ke kiri bawah"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Putar <xliff:g id="SONG_NAME">%1$s</xliff:g> dari <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Urungkan"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Dekatkan untuk memutar di <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Dekatkan ke <xliff:g id="DEVICENAME">%1$s</xliff:g> untuk memutar di sini"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Diputar di <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Terjadi error. Coba lagi."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Memuat"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speaker & Layar"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara kerja siaran"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Siaran"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang di dekat Anda dengan perangkat Bluetooth yang kompatibel dapat mendengarkan media yang sedang Anda siarkan"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Layar ini akan dinonaktifkan"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Perangkat foldable sedang dibentangkan"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Perangkat foldable sedang dibalik"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Baterai stilus lemah"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 8585ca7..aa76263 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Neðri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vinstri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Hægri mörk <xliff:g id="PERCENT">%1$d</xliff:g> prósent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Skjáupptaka"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Miðlungs"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Lítið"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Stórt"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Loka"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Breyta"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Stillingar stækkunarglugga"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ýttu til að opna aðgengiseiginleika. Sérsníddu eða skiptu hnappinum út í stillingum.\n\n"<annotation id="link">"Skoða stillingar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Færðu hnappinn að brúninni til að fela hann tímabundið"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Afturkalla"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Flýtileiðin <xliff:g id="FEATURE_NAME">%s</xliff:g> var fjarlægð"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# flýtileið var fjarlægð}one{# flýtileið var fjarlægð}other{# flýtileiðir voru fjarlægðar}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Færa efst til vinstri"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Færa efst til hægri"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Færa neðst til vinstri"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spila <xliff:g id="SONG_NAME">%1$s</xliff:g> í <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Afturkalla"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Færðu nær til að spila í <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Færðu tækið nær <xliff:g id="DEVICENAME">%1$s</xliff:g> til að spila hér"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Í spilun í <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Eitthvað fór úrskeiðis. Reyndu aftur."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Hleður"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hljóðstyrkur"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hátalarar og skjáir"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Svona virkar útsending"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Útsending"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Fólk nálægt þér með samhæf Bluetooth-tæki getur hlustað á efnið sem þú sendir út"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Slökkt verður á þessum skjá"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Samanbrjótanlegt tæki opnað"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Samanbrjótanlegu tæki snúið við"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Rafhlaða pennans er að tæmast"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index d2d022f..e3cca72 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inferiore, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite sinistro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite destro, <xliff:g id="PERCENT">%1$d</xliff:g> percento"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Registrazione dello schermo"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaboraz. registraz. schermo"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
@@ -382,7 +386,7 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Il servizio che offre questa funzione avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vuoi avviare la registrazione o la trasmissione?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Vuoi avviare la registrazione o la trasmissione con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Consenti a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> di condividere o registrare?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Consentire a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> di condividere o registrare?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Schermo intero"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Una sola app"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Quando condividi, registri o trasmetti, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ha accesso a qualsiasi elemento visibile sul tuo schermo o in riproduzione sul tuo dispositivo. Presta quindi attenzione a password, dati di pagamento, messaggi o altre informazioni sensibili."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medio"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Piccolo"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Chiudi"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Modifica"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Impostazioni della finestra di ingrandimento"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tocca per aprire funzioni di accessibilità. Personalizza o sostituisci il pulsante in Impostazioni.\n\n"<annotation id="link">"Vedi impostazioni"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sposta il pulsante fino al bordo per nasconderlo temporaneamente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Elimina"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Scorciatoia <xliff:g id="FEATURE_NAME">%s</xliff:g> rimossa"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# scorciatoia rimossa}many{# scorciatoie rimosse}other{# scorciatoie rimosse}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sposta in alto a sinistra"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sposta in alto a destra"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Sposta in basso a sinistra"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Riproduci <xliff:g id="SONG_NAME">%1$s</xliff:g> da <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Annulla"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Avvicinati per riprodurre su <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Avvicinati a <xliff:g id="DEVICENAME">%1$s</xliff:g> per riprodurre i contenuti qui"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"In riproduzione su <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Si è verificato un errore. Riprova."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Caricamento in corso…"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speaker e display"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Come funziona la trasmissione"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Annuncio"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Le persone vicine a te che hanno dispositivi Bluetooth compatibili possono ascoltare i contenuti multimediali che stai trasmettendo"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Questo schermo verrà disattivato"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo pieghevole che viene aperto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo pieghevole che viene capovolto"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Batteria stilo in esaurimento"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index f53f702..5b55241 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים התחתונים"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים השמאליים"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> אחוז מהשוליים הימניים"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"צילומי מסך בפרופיל העבודה נשמרים באפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"קבצים"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"מקליט המסך"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
@@ -98,8 +100,8 @@
<string name="screenrecord_description" msgid="1123231719680353736">"בזמן ההקלטה, מערכת Android יכולה לתעד מידע רגיש שגלוי במסך או מופעל במכשיר שלך. מידע זה כולל סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו."</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"הקלטה של כל המסך"</string>
<string name="screenrecord_option_single_app" msgid="5954863081500035825">"הקלטה של אפליקציה אחת"</string>
- <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"בזמן ההקלטה, תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
- <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"בזמן הקלטה של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"בזמן ההקלטה, תהיה ל-Android גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. חשוב להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+ <string name="screenrecord_warning_single_app" msgid="7760723997065948283">"בזמן הקלטה של אפליקציה, תהיה ל-Android גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. חשוב להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"התחלת ההקלטה"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"הקלטת אודיו"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"אודיו מהמכשיר"</string>
@@ -385,8 +387,8 @@
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"לאפשר לאפליקציה <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> לשתף או להקליט?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"כל המסך"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"אפליקציה אחת"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. כדאי להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"בזמן שיתוף, הקלטה או העברה (cast) תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך. חשוב להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"בזמן שיתוף, הקלטה או העברה (cast) של אפליקציה, תהיה ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> גישה לכל מה שגלוי באפליקציה או מופעל מהאפליקציה. חשוב להיזהר עם סיסמאות, פרטי תשלום, הודעות או מידע רגיש אחר."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"המשך"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"שיתוף או הקלטה של אפליקציה"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"לאפשר לאפליקציה הזו לשתף או להקליט?"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"בינוני"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"קטן"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"גדול"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"סגירה"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"עריכה"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ההגדרות של חלון ההגדלה"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"מקישים כדי לפתוח את תכונות הנגישות. אפשר להחליף את הלחצן או להתאים אותו אישית בהגדרות.\n\n"<annotation id="link">"הצגת ההגדרות"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"כדי להסתיר זמנית את הלחצן, יש להזיז אותו לקצה"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ביטול"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"קיצור הדרך אל <xliff:g id="FEATURE_NAME">%s</xliff:g> הוסר"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{קיצור הדרך הוסר}one{# קיצורי דרך הוסרו}two{# קיצורי דרך הוסרו}other{# קיצורי דרך הוסרו}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"העברה לפינה השמאלית העליונה"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"העברה לפינה הימנית העליונה"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"העברה לפינה השמאלית התחתונה"</string>
@@ -883,12 +884,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> של <xliff:g id="ARTIST_NAME">%2$s</xliff:g> מ-<xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"הפעלת <xliff:g id="SONG_NAME">%1$s</xliff:g> מ-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ביטול"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"צריך להתקרב כדי להפעיל מוזיקה במכשיר <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"צריך להתקרב אל <xliff:g id="DEVICENAME">%1$s</xliff:g> כדי להפעיל כאן"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"צריך להתקרב כדי להפעיל מדיה במכשיר <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"פועלת ב-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"משהו השתבש. יש לנסות שוב."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"בטעינה"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"טאבלט"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"עוצמת הקול"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"רמקולים ומסכים"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"הצעות למכשירים"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"הסבר על שידורים"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"שידור"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"אנשים בקרבת מקום עם מכשירי Bluetooth תואמים יכולים להאזין למדיה שמשודרת על ידך"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ המסך יכבה"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"מכשיר מתקפל עובר למצב לא מקופל"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"מכשיר מתקפל עובר למצב מהופך"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"הסוללה של הסטיילוס חלשה"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4715126..96f7758 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下部の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右の境界線 <xliff:g id="PERCENT">%1$d</xliff:g> パーセント"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"スクリーン レコーダー"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"小"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"大"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"閉じる"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"編集"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"拡大鏡ウィンドウの設定"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"タップしてユーザー補助機能を開きます。ボタンのカスタマイズや入れ替えを [設定] で行えます。\n\n"<annotation id="link">"設定を表示"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ボタンを一時的に非表示にするには、端に移動させてください"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"元に戻す"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> 個のショートカットを削除"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# 個のショートカットを削除}other{# 個のショートカットを削除}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"左上に移動"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"右上に移動"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"左下に移動"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> を <xliff:g id="APP_LABEL">%2$s</xliff:g> で再生"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"元に戻す"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>で再生するにはもっと近づけてください"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ここで再生するには<xliff:g id="DEVICENAME">%1$s</xliff:g>に近づいてください"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>で再生しています"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"エラーが発生しました。もう一度お試しください。"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"読み込んでいます"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"スピーカーとディスプレイ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ブロードキャストの仕組み"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ブロードキャスト"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Bluetooth 対応デバイスを持っている付近のユーザーは、あなたがブロードキャストしているメディアを聴けます"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱この画面は OFF になります"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"折りたたみ式デバイスが広げられている"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"折りたたみ式デバイスがひっくり返されている"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"タッチペンのバッテリー残量が少なくなっています"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index a031af4..5f9b6e1 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ქვედა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"მარცხენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"მარჯვენა ზღვარი: <xliff:g id="PERCENT">%1$d</xliff:g> პროცენტი"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"სამუშაო ეკრანის ანაბეჭდები ინახება <xliff:g id="APP">%1$s</xliff:g> აპში"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ფაილები"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"ეკრანის ჩამწერი"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
@@ -98,7 +100,7 @@
<string name="screenrecord_description" msgid="1123231719680353736">"ჩაწერის განმავლობაში Android სისტემას შეუძლია აღბეჭდოს ნებისმიერი სენსიტიური ინფორმაცია, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება. აღნიშნული მოიცავს პაროლებს, გადახდის დეტალებს, ფოტოებს, შეტყობინებებსა და აუდიოს."</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"მთელი ეკრანის ჩაწერა"</string>
<string name="screenrecord_option_single_app" msgid="5954863081500035825">"ერთი აპის ჩაწერა"</string>
- <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"სანამ აპის ჩაწერას ახორციელებთ, Android-ს აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენი მოწყობილობის მეშვეობით. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა მგრძნობიარე ინფორმაციასთან."</string>
+ <string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"ჩაწერის განხორციელებისას Android-ს აქვს წვდომა ყველაფერზე, რაც თქვენს ეკრანზე ჩანს ან უკრავს თქვენი მოწყობილობის მეშვეობით. შესაბამისად, გამოიჩინეთ სიფრთხილე პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან თუ სხვა მგრძნობიარე ინფორმაციასთან დაკავშირებით."</string>
<string name="screenrecord_warning_single_app" msgid="7760723997065948283">"სანამ აპის ჩაწერას ახორციელებთ, Android-ს აქვს წვდომა ყველაფერზე, რაც ჩანს აპში ან ითამაშეთ. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა მგრძნობიარე ინფორმაციასთან"</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"ჩაწერის დაწყება"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"აუდიოს ჩაწერა"</string>
@@ -382,11 +384,11 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"ამ ფუნქციის მომწოდებელ სერვისს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"დაიწყოს ჩაწერა ან ტრანსლირება?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"დაიწყოს ჩაწერა ან ტრანსლირება <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ით?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"გსურთ დართოთ ნება <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> გაზიარების ან ჩაწერისთვის?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"გსურთ, დართოთ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს გაზიარების ან ჩაწერის ნება?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"მთელი ეკრანი"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"ერთი აპი"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"როდესაც თქვენ აზიარებთ, ჩაწერთ ან ტრანსლირებთ, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> აქვს წვდომა ყველაფერზე, რაც ჩანს თქვენს ეკრანზე ან უკრავს თქვენს მოწყობილობაზე. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა მგრძნობიარე ინფორმაციასთან."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> აქვს წვდომა აქვს ყველაფერზე, რაც ჩანს აპში ან ითამაშეთ. ამიტომ იყავით ფრთხილად პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან ან სხვა მგრძნობიარე ინფორმაციასთან."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"აპის გაზიარებისას, ჩაწერისას ან ტრანსლირებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-ს აქვს წვდომა ყველაფერზე, რაც ამ აპში ჩანს და მასშია გაშვებული. შესაბამისად, გამოიჩინეთ სიფრთხილე პაროლებთან, გადახდის დეტალებთან, შეტყობინებებთან თუ სხვა მგრძნობიარე ინფორმაციასთან დაკავშირებით."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"გაგრძელება"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"გააზიარეთ ან ჩაწერეთ აპი"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"გსურთ ამ აპისთვის გაზიარების ან ჩაწერის უფლების მიცემა?"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"საშუალო"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"პატარა"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"დიდი"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"დახურვა"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"რედაქტირება"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"გადიდების ფანჯრის პარამეტრები"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"შეეხეთ მარტივი წვდომის ფუნქციების გასახსნელად. მოარგეთ ან შეცვალეთ ეს ღილაკი პარამეტრებში.\n\n"<annotation id="link">"პარამეტრების ნახვა"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"გადაიტანეთ ღილაკი კიდეში, რათა დროებით დამალოთ ის"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"მოქმედების გაუქმება"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> მალსახმობი ამოშლილია"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# მალსახმობი ამოშლილია}other{# მალსახმობი ამოშლილია}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ზევით და მარცხნივ გადატანა"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ზევით და მარჯვნივ გადატანა"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ქვევით და მარცხნივ გადატანა"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"დაუკარით <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g>-დან"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"მოქმედების გაუქმება"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"მიიტანეთ უფრო ახლოს, რომ დაუკრათ <xliff:g id="DEVICENAME">%1$s</xliff:g>-ზე"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"მიუახლოვდით <xliff:g id="DEVICENAME">%1$s</xliff:g>-ს მისი მეშვეობით დასაკრავად"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"მიმდინარეობს დაკვრა <xliff:g id="DEVICENAME">%1$s</xliff:g>-ზე"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"რაღაც შეცდომა მოხდა. ცადეთ ხელახლა."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"იტვირთება"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"ტაბლეტი"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ხმა"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"დინამიკები და დისპლეები"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"შემოთავაზებული მოწყობილობები"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ტრანსლირების მუშაობის პრინციპი"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ტრანსლაცია"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"თქვენთან ახლოს მყოფ ხალხს თავსებადი Bluetooth მოწყობილობით შეუძლიათ თქვენ მიერ ტრანსლირებული მედიის მოსმენა"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ეს ეკრანი გამოირთვება"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"დასაკეცი მოწყობილობა იხსნება"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"დასაკეცი მოწყობილობა ტრიალებს"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"სტილუსის ბატარეა დაცლის პირასაა"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index aa1f9e3..77c586a 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Төменгі шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жақ шектік сызық: <xliff:g id="PERCENT">%1$d</xliff:g> пайыз"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Экран жазғыш"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Орташа"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Кішi"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Үлкен"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Жабу"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Өзгерту"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Ұлғайтқыш терезесінің параметрлері"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Арнайы мүмкіндікті ашу үшін түртіңіз. Түймені параметрден реттеңіз не ауыстырыңыз.\n\n"<annotation id="link">"Параметрді көру"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Түймені уақытша жасыру үшін оны шетке қарай жылжытыңыз."</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Қайтару"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> таңбашасы өшірілді."</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# таңбаша өшірілді.}other{# таңбаша өшірілді.}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жоғарғы сол жаққа жылжыту"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Жоғарғы оң жаққа жылжыту"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Төменгі сол жаққа жылжыту"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> қолданбасында \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" әнін ойнату"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Қайтару"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысында музыка ойнату үшін оған жақындаңыз."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Осы жерде ойнау үшін <xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысына жақындаңыз"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> құрылғысында ойнатылуда."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Бірдеңе дұрыс болмады. Қайталап көріңіз."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Жүктеліп жатыр"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Дыбыс деңгейі"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Динамиктер мен дисплейлер"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Тарату қалай жүзеге асады"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Тарату"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Үйлесімді Bluetooth құрылғылары бар маңайдағы адамдар сіз таратып жатқан медиамазмұнды тыңдай алады."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бұл экран өшіріледі."</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Бүктемелі құрылғы ашылып жатыр."</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Бүктемелі құрылғы аударылып жатыр."</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Стилус батареясының заряды аз"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index ce7f702..a191a14 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"បន្ទាត់បែងចែកខាងក្រោម <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"បន្ទាត់បែងចែកខាងឆ្វេង <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"បន្ទាត់បែងចែកខាងស្ដាំ <xliff:g id="PERCENT">%1$d</xliff:g> ភាគរយ"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"មុខងារថតវីដេអូអេក្រង់"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុងដំណើរការការថតអេក្រង់"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹងដែលកំពុងដំណើរការសម្រាប់រយៈពេលប្រើការថតសកម្មភាពអេក្រង់"</string>
@@ -382,7 +386,7 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"សេវាកម្មដែលផ្ដល់មុខងារនេះនឹងមានសិទ្ធិចូលប្រើព័ត៌មានទាំងអស់ដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬដែលចាក់ពីឧបករណ៍របស់អ្នក នៅពេលកំពុងថត ឬភ្ជាប់។ ព័ត៌មាននេះមានដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ រូបថត សារ និងសំឡេងដែលអ្នកចាក់ជាដើម។"</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ចាប់ផ្ដើមថត ឬភ្ជាប់មែនទេ?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"ចាប់ផ្ដើមថត ឬភ្ជាប់ដោយប្រើ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"អនុញ្ញាតឱ្យ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ចែករំលែក ឬថតទេ?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"អនុញ្ញាតឱ្យ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ចែករំលែក ឬថត?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"អេក្រង់ទាំងមូល"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"កម្មវិធីតែមួយ"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"នៅពេលអ្នកកំពុងចែករំលែក ថត ឬបញ្ជូន <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មានសិទ្ធិចូលប្រើប្រាស់អ្វីៗដែលបង្ហាញឱ្យឃើញនៅលើអេក្រង់របស់អ្នក ឬលេងនៅលើឧបករណ៍របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ ឬព័ត៌មានរសើបផ្សេងទៀត។"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"មធ្យម"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"តូច"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ធំ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"បិទ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"កែ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ការកំណត់វិនដូកម្មវិធីពង្រីក"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ចុចដើម្បីបើកមុខងារភាពងាយស្រួល។ ប្ដូរ ឬប្ដូរប៊ូតុងនេះតាមបំណងនៅក្នុងការកំណត់។\n\n"<annotation id="link">"មើលការកំណត់"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ផ្លាស់ទីប៊ូតុងទៅគែម ដើម្បីលាក់វាជាបណ្ដោះអាសន្ន"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ត្រឡប់វិញ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"បានដកផ្លូវកាត់ <xliff:g id="FEATURE_NAME">%s</xliff:g> ចេញ"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{បានដកផ្លូវកាត់ # ចេញ}other{បានដកផ្លូវកាត់ # ចេញ}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងឆ្វេង"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងស្ដាំ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ផ្លាស់ទីទៅខាងក្រោមផ្នែកខាងឆ្វេង"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ចាក់ <xliff:g id="SONG_NAME">%1$s</xliff:g> ពី <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ត្រឡប់វិញ"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"រំកិលឱ្យកាន់តែជិត ដើម្បីចាក់នៅលើ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"រំកិលឱ្យកាន់តែជិត <xliff:g id="DEVICENAME">%1$s</xliff:g> ដើម្បីចាក់នៅទីនេះ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"កំពុងចាក់នៅលើ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"មានអ្វីមួយខុសប្រក្រតី។ សូមព្យាយាមម្ដងទៀត។"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"កំពុងផ្ទុក"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើលកម្មវិធី"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"រកមិនឃើញទេ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"កម្រិតសំឡេង"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ឧបករណ៍បំពងសំឡេង និងផ្ទាំងអេក្រង់"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"របៀបដែលការផ្សាយដំណើរការ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ការផ្សាយ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"មនុស្សនៅជិតអ្នកដែលមានឧបករណ៍ប៊្លូធូសត្រូវគ្នាអាចស្តាប់មេឌៀដែលអ្នកកំពុងផ្សាយបាន"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ អេក្រង់នេះនឹងបិទ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ឧបករណ៍អាចបត់បានកំពុងត្រូវបានលា"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ឧបករណ៍អាចបត់បានកំពុងត្រូវបានលា"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ថ្មប៊ិកនៅសល់តិច"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 34f8e9a..652a227 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ಕೆಳಗಿನ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ಎಡಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ಬಲಭಾಗದ ಬೌಂಡರಿ ಶೇಕಡಾ <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ಮಧ್ಯಮ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ಚಿಕ್ಕದು"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ದೊಡ್ಡದು"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ಮುಚ್ಚಿರಿ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ಮ್ಯಾಗ್ನಿಫೈರ್ ವಿಂಡೋ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಈ ಬಟನ್ ಅನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ ಅಥವಾ ಬದಲಾಯಿಸಿ.\n\n"<annotation id="link">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ಅದನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಮರೆಮಾಡಲು ಅಂಚಿಗೆ ಬಟನ್ ಸರಿಸಿ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ರದ್ದುಗೊಳಿಸಿ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ಶಾರ್ಟ್ಕಟ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ಶಾರ್ಟ್ಕಟ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ}one{# ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ}other{# ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ಎಡ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ಬಲ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ಸ್ಕ್ರೀನ್ನ ಎಡ ಕೆಳಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ರದ್ದುಗೊಳಿಸಿ"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು ಅದರ ಹತ್ತಿರಕ್ಕೆ ಸರಿಯಿರಿ"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ಇಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲು <xliff:g id="DEVICENAME">%1$s</xliff:g> ಸಮೀಪಕ್ಕೆ ಹೋಗಿ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತಿದೆ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ಏನೋ ತಪ್ಪಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ಲೋಡ್ ಆಗುತ್ತಿದೆ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ಕಂಡುಬಂದಿಲ್ಲ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ವಾಲ್ಯೂಮ್"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ಸ್ಪೀಕರ್ಗಳು ಮತ್ತು ಡಿಸ್ಪ್ಲೇಗಳು"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ಪ್ರಸಾರವು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ಪ್ರಸಾರ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ಹೊಂದಾಣಿಕೆಯಾಗುವ ಬ್ಲೂಟೂತ್ ಸಾಧನಗಳನ್ನು ಹೊಂದಿರುವ ಸಮೀಪದಲ್ಲಿರುವ ಜನರು ನೀವು ಪ್ರಸಾರ ಮಾಡುತ್ತಿರುವ ಮಾಧ್ಯಮವನ್ನು ಆಲಿಸಬಹುದು"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ಈ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಅನ್ಫೋಲ್ಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ಫೋಲ್ಡ್ ಮಾಡಬಹುದಾದ ಸಾಧನವನ್ನು ಸುತ್ತಲೂ ತಿರುಗಿಸಲಾಗುತ್ತಿದೆ"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ಸ್ಟೈಲಸ್ ಬ್ಯಾಟರಿ ಕಡಿಮೆಯಿದೆ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index eb899a7..2346774 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"하단 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"왼쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"오른쪽 가장자리 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"화면 녹화"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
@@ -382,11 +386,11 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 재생하는 오디오 같은 정보가 포함됩니다."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"녹화 또는 전송을 시작하시겠습니까?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>으로 녹화 또는 전송을 시작하시겠습니까?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 공유 또는 녹화를 허용할까요?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 공유 또는 녹화하도록 허용할까요?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"전체 화면"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"단일 앱"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"공유하거나 녹화하거나 전송할 때 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱에서 화면에 표시되거나 기기에서 재생되는 모든 항목에 액세스할 수 있습니다. 따라서 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"앱을 공유하거나 녹화하거나 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 해당 앱에 표시되거나 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"앱을 공유하거나 녹화하거나 전송할 때는 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에서 해당 앱에 표시되거나 앱에서 재생되는 모든 항목에 액세스할 수 있으므로 비밀번호, 결제 세부정보, 메시지 등 민감한 정보가 노출되지 않도록 주의하세요."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"계속"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"앱 공유 또는 녹화"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"앱에서 공유하거나 기록하도록 허용하시겠습니까?"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"보통"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"작게"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"크게"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"닫기"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"수정"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"돋보기 창 설정"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"접근성 기능을 열려면 탭하세요. 설정에서 이 버튼을 맞춤설정하거나 교체할 수 있습니다.\n\n"<annotation id="link">"설정 보기"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요."</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"실행취소"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"바로가기 <xliff:g id="FEATURE_NAME">%s</xliff:g>개 삭제됨"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{바로가기 #개 삭제됨}other{바로가기 #개 삭제됨}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"왼쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"오른쪽 상단으로 이동"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"왼쪽 하단으로 이동"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>에서 <xliff:g id="SONG_NAME">%1$s</xliff:g> 재생"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"실행취소"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>에서 재생하려면 기기를 더 가까이로 옮기세요."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"현재 기기에서 재생하려면 <xliff:g id="DEVICENAME">%1$s</xliff:g>에 더 가까이 이동합니다."</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>에서 재생 중"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"문제가 발생했습니다. 다시 시도해 주세요."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"로드 중"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"볼륨"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"스피커 및 디스플레이"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"브로드캐스팅 작동 원리"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"브로드캐스트"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"호환되는 블루투스 기기를 가진 근처의 사용자가 내가 브로드캐스트 중인 미디어를 수신 대기할 수 있습니다."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 이 화면이 꺼집니다."</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"폴더블 기기를 펼치는 모습"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"폴더블 기기를 뒤집는 모습"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"스타일러스 배터리 부족"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 08ef2a6..c05fae2 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ылдый жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Сол жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Оң жагы <xliff:g id="PERCENT">%1$d</xliff:g> пайызга"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"экрандан видео жаздырып алуу"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
@@ -382,16 +386,16 @@
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Жаздырып же тышкы экранга чыгарып жатканда, бул колдонмо экраныңыздагы бардык маалыматты же түзмөктө ойнолуп жаткан бардык нерселерди (сырсөздөрдү, төлөмдүн чоо-жайын, сүрөттөрдү, билдирүүлөрдү жана угуп жаткан аудиофайлдарды) көрө алат."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Жаздырып же тышкы экранга чыгарып баштайсызбы?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосу аркылуу жаздырып же тышкы экранга чыгарып баштайсызбы?"</string>
- <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна бөлүшүүгө же жаздырууга уруксат бересизби?"</string>
+ <string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна экранды бөлүшүүгө же андан видео тартууга уруксат бересизби?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Бүтүндөй экран"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Жалгыз колдонмо"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Бөлүшүп, жаздырып же тышкы экранда бөлүшкөндө <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөм маалыматын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Бөлүшүп, жаздырып же тышкы экранда бөлүшкөндө <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ал колдонмодо көрүнүп жана ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөм маалыматын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Экранды көрсөтүп, тышка чыгарып же андан видео тартып жатканда, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> түзмөктүн экранындагы нерселердин баарын көрө алат. Андыктан сырсөздөр, төлөм маалыматы, билдирүүлөр сыяктуу купуя маалыматты киргизүүдө же көрүүдө этият болуңуз."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Экранды көрсөтүп, тышка чыгарып же андан видео тартып жатканда, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> түзмөктүн экранындагы нерселердин баарын көрө алат. Андыктан сырсөздөр, төлөм маалыматы, билдирүүлөр сыяктуу купуя маалыматты киргизүүдө же көрүүдө этият болуңуз."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Улантуу"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Колдонмону бөлүшүү же жаздыруу"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Бул колдонмого бөлүшүп же жаздырууга уруксат бересизби?"</string>
- <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Бөлүшүп, жаздырып же тышкы экранга чыгарганда бул колдонмо экраныңызда көрүнүп жана түзмөктө ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
- <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Бөлүшүп, жаздырып же тышкы экранга чыгарганда бул колдонмо ал колдонмодо көрсөтүлүп жана ойнотулуп жаткан нерселерге мүмкүнчүлүк алат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү жана башка купуя маалыматты көрсөтүп албаңыз."</string>
+ <string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Экранды көрсөтүп, тышка чыгарып же андан видео тартып жатканда, бул колдонмо түзмөктүн экранындагы нерселердин баарын көрө алат. Андыктан сырсөздөр, төлөм маалыматы, билдирүүлөр сыяктуу купуя маалыматты киргизүүдө же көрүүдө этият болуңуз."</string>
+ <string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Экранды көрсөтүп, тышка чыгарып же андан видео тартып жатканда, бул колдонмо түзмөктүн экранындагы нерселердин баарын көрө алат. Андыктан сырсөздөр, төлөм маалыматы, билдирүүлөр сыяктуу купуя маалыматты киргизүүдө же көрүүдө этият болуңуз."</string>
<string name="screen_capturing_disabled_by_policy_dialog_title" msgid="2113331792064527203">"IT администраторуңуз бөгөттөп койгон"</string>
<string name="screen_capturing_disabled_by_policy_dialog_description" msgid="6015975736747696431">"Түзмөк саясаты экрандагыны тартып алууну өчүрүп койгон"</string>
<string name="clear_all_notifications_text" msgid="348312370303046130">"Баарын тазалап салуу"</string>
@@ -756,7 +760,7 @@
<string name="auto_data_switch_disable_message" msgid="5885533647399535852">"Жеткиликтүү болгондо мобилдик Интернет автоматтык түрдө которулбайт"</string>
<string name="auto_data_switch_dialog_negative_button" msgid="2370876875999891444">"Жок, рахмат"</string>
<string name="auto_data_switch_dialog_positive_button" msgid="8531782041263087564">"Ооба, которулуу"</string>
- <string name="touch_filtered_warning" msgid="8119511393338714836">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Жөндөөлөр жообуңузду ырастай албай жатат."</string>
+ <string name="touch_filtered_warning" msgid="8119511393338714836">"Уруксат берүү сурамыңыз көрүнбөй калгандыктан, Параметрлер жообуңузду ырастай албай жатат."</string>
<string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосуна <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөтүүгө уруксат берилсинби?"</string>
<string name="slice_permission_text_1" msgid="6675965177075443714">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунун маалыматын окуйт"</string>
<string name="slice_permission_text_2" msgid="6758906940360746983">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунда аракеттерди аткарат"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Орто"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Кичине"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Чоң"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Жабуу"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Түзөтүү"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Чоңойткуч терезесинин параметрлери"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Атайын мүмкүнчүлүктөрдү ачуу үчүн басыңыз. Бул баскычты Жөндөөлөрдөн өзгөртүңүз.\n\n"<annotation id="link">"Жөндөөлөрдү көрүү"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Баскычты убактылуу жашыра туруу үчүн экрандын четине жылдырыңыз"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Кайтаруу"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ыкчам баскычы өчүрүлдү"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ыкчам баскыч өчүрүлдү}other{# ыкчам баскыч өчүрүлдү}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жогорку сол жакка жылдыруу"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Жогорку оң жакка жылдыруу"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Төмөнкү сол жакка жылдыруу"</string>
@@ -870,7 +873,7 @@
<string name="controls_media_active_session" msgid="3146882316024153337">"Учурдагы медиа сеансын жашыруу мүмкүн эмес."</string>
<string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жашыруу"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
- <string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string>
+ <string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
<string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ыры (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотулуп жатат"</string>
<string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> ичинен <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
<string name="controls_media_button_play" msgid="2705068099607410633">"Ойнотуу"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын (аткаруучу: <xliff:g id="ARTIST_NAME">%2$s</xliff:g>) <xliff:g id="APP_LABEL">%3$s</xliff:g> колдонмосунан ойнотуу"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ырын <xliff:g id="APP_LABEL">%2$s</xliff:g> колдонмосунан ойнотуу"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Кайтаруу"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүндө ойнотуу үчүн жакыныраак жылдырыңыз"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Бул жерде ойнотуу үчүн <xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүнө жакындатыңыз"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> түзмөгүндө ойнотуу үчүн жакындатыңыз"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> аркылуу ойнотулууда"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Бир жерден ката кетти. Кайра аракет кылыңыз."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Жүктөлүүдө"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Табылган жок"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Үндүн катуулугу"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Динамиктер жана дисплейлер"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Кабарлоо кантип иштейт"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Кабарлоо"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Шайкеш Bluetooth түзмөктөрү болгон жакын жердеги кишилер кабарлап жаткан медиаңызды уга алышат"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Бул экран өчөт"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ачылып турган бүктөлмө түзмөк"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Оодарылып жаткан бүктөлмө түзмөк"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Стилустун батареясы отурайын деп калды"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 787a139..7af21e8 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ຂອບເຂດທາງລຸ່ມ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ຂອບເຂດທາງຊ້າຍ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ຂອບເຂດທາງຂວາ <xliff:g id="PERCENT">%1$d</xliff:g> ເປີເຊັນ"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ປານກາງ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ນ້ອຍ"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ໃຫຍ່"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ປິດ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ແກ້ໄຂ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ການຕັ້ງຄ່າໜ້າຈໍຂະຫຍາຍ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ແຕະເພື່ອເປີດຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ປັບແຕ່ງ ຫຼື ປ່ຽນປຸ່ມນີ້ໃນການຕັ້ງຄ່າ.\n\n"<annotation id="link">"ເບິ່ງການຕັ້ງຄ່າ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ຍ້າຍປຸ່ມໄປໃສ່ຂອບເພື່ອເຊື່ອງມັນຊົ່ວຄາວ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ຍົກເລີກ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"ລຶບທາງລັດ <xliff:g id="FEATURE_NAME">%s</xliff:g> ອອກແລ້ວ"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{ລຶບ # ທາງລັດອອກແລ້ວ}other{ລຶບ # ທາງລັດອອກແລ້ວ}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ຍ້າຍຊ້າຍເທິງ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ຍ້າຍຂວາເທິງ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ຍ້າຍຊ້າຍລຸ່ມ"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"ຫຼິ້ນ <xliff:g id="SONG_NAME">%1$s</xliff:g> ຈາກ <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ຍົກເລີກ"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"ຍ້າຍໄປໃກ້ຂຶ້ນເພື່ອຫຼິ້ນຢູ່ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ກະລຸນາຍ້າຍເຂົ້າໃກ້ <xliff:g id="DEVICENAME">%1$s</xliff:g> ເພື່ອຫຼິ້ນຢູ່ບ່ອນນີ້"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"ກຳລັງຫຼິ້ນຢູ່ <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ມີບາງຢ່າງຜິດພາດເກີດຂຶ້ນ. ກະລຸນາລອງໃໝ່."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ກຳລັງໂຫຼດ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ບໍ່ພົບ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ລະດັບສຽງ"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ລຳໂພງ ແລະ ຈໍສະແດງຜົນ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ການອອກອາກາດເຮັດວຽກແນວໃດ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ອອກອາກາດ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ຄົນທີ່ຢູ່ໃກ້ທ່ານທີ່ມີອຸປະກອນ Bluetooth ທີ່ເຂົ້າກັນໄດ້ຈະສາມາດຟັງມີເດຍທີ່ທ່ານກຳລັງອອກອາກາດຢູ່ໄດ້"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ໜ້າຈໍນີ້ຈະປິດ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ອຸປະກອນທີ່ພັບໄດ້ກຳລັງກາງອອກ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ອຸປະກອນທີ່ພັກໄດ້ກຳລັງປີ້ນໄປມາ"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ແບັດເຕີຣີປາກກາເຫຼືອໜ້ອຍ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a1d4b18..cdf134c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Apatinė riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kairioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Dešinioji riba – <xliff:g id="PERCENT">%1$d</xliff:g> proc."</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrano vaizdo įrašytuvas"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vidutinis"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Mažas"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Didelis"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Uždaryti"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Redaguoti"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Didinimo lango nustatymai"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Palietę atidarykite pritaikymo neįgaliesiems funkcijas. Tinkinkite arba pakeiskite šį mygtuką nustatymuose.\n\n"<annotation id="link">"Žr. nustatymus"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Perkelkite mygtuką prie krašto, kad laikinai jį paslėptumėte"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anuliuoti"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pašalintas spart. klavišas „<xliff:g id="FEATURE_NAME">%s</xliff:g>“"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Pašalintas # spartusis klavišas}one{Pašalintas # spartusis klavišas}few{Pašalinti # spartieji klavišai}many{Pašalinta # sparčiojo klavišo}other{Pašalinta # sparčiųjų klavišų}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Perkelti į viršų kairėje"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Perkelti į viršų dešinėje"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Perkelti į apačią kairėje"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Leisti „<xliff:g id="SONG_NAME">%1$s</xliff:g>“ iš „<xliff:g id="APP_LABEL">%2$s</xliff:g>“"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Anuliuoti"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Prieikite arčiau, kad galėtumėte leisti įrenginyje „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Perkelkite arčiau „<xliff:g id="DEVICENAME">%1$s</xliff:g>“, kad būtų galima leisti čia"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Leidžiama įrenginyje „<xliff:g id="DEVICENAME">%1$s</xliff:g>“"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kažkas ne taip. Bandykite dar kartą."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Įkeliama"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nerasta"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Garsumas"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Garsiakalbiai ir ekranai"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kaip veikia transliacija"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transliacija"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Netoliese esantys žmonės, turintys suderinamus „Bluetooth“ įrenginius, gali klausyti jūsų transliuojamos medijos"</string>
@@ -1053,5 +1060,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekranas išsijungs"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Lankstomasis įrenginys išlankstomas"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Lankstomasis įrenginys apverčiamas"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Senka rašiklio akumuliatorius"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Liko akumuliatoriaus įkrovos: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Prijunkite rašiklį prie kroviklio"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c1acb3f..603b2b6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Apakšmala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kreisā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Labā mala: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrāna ierakstītājs"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vidējs"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Mazs"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Liels"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Aizvērt"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Rediģēt"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Lupas loga iestatījumi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Atveriet pieejamības funkcijas. Pielāgojiet vai aizstājiet šo pogu iestatījumos.\n\n"<annotation id="link">"Skatīt iestatījumus"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Lai īslaicīgi paslēptu pogu, pārvietojiet to uz malu"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Atsaukt"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Noņemts īsinājumtaustiņš <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Noņemts # īsinājumtaustiņš}zero{Noņemti # īsinājumtaustiņi}one{Noņemts # īsinājumtaustiņš}other{Noņemti # īsinājumtaustiņi}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pārvietot augšpusē pa kreisi"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Pārvietot augšpusē pa labi"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Pārvietot apakšpusē pa kreisi"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Atskaņojiet failu “<xliff:g id="SONG_NAME">%1$s</xliff:g>” no lietotnes <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Atsaukt"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Pārvietojiet savu ierīci tuvāk, lai atskaņotu mūziku ierīcē “<xliff:g id="DEVICENAME">%1$s</xliff:g>”."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Pārvietojieties tuvāk ierīcei “<xliff:g id="DEVICENAME">%1$s</xliff:g>”, lai atskaņotu šeit"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Notiek atskaņošana ierīcē <xliff:g id="DEVICENAME">%1$s</xliff:g>."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Radās kļūda. Mēģiniet vēlreiz."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Notiek ielāde"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Skaļums"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Skaļruņi un displeji"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kā darbojas apraide"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Apraide"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Tuvumā esošās personas ar saderīgām Bluetooth ierīcēm var klausīties jūsu apraidīto multivides saturu."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Šis ekrāns tiks izslēgts."</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Salokāma ierīce tiek atlocīta"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Salokāma ierīce tiek apgriezta"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Zems skārienekrāna pildspalvas akumulatora līmenis"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 133cb6e..e1280b8 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Долна граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна граница <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Сликите од екранот во работниот профил се зачувуваат во апликацијата <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Датотеки"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Снимач на екран"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средно"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Мало"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Големо"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Затвори"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Изменете"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Поставки за прозорец за лупа"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Допрете за функциите за пристапност. Приспособете или заменете го копчево во „Поставки“.\n\n"<annotation id="link">"Прикажи поставки"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете го копчето до работ за да го сокриете привремено"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Врати"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Отстранета е кратенката за <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Отстранета е # кратенка}one{Отстранети се # кратенка}other{Отстранети се # кратенки}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Премести горе десно"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Премести долу лево"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пуштете <xliff:g id="SONG_NAME">%1$s</xliff:g> на <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Врати"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Приближете се за да пуштите на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближете се до <xliff:g id="DEVICENAME">%1$s</xliff:g> за да пуштите тука"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Пуштено на <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Нешто не е во ред. Обидете се повторно."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Се вчитува"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"таблет"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Јачина на звук"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Звучници и екрани"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Предложени уреди"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционира емитувањето"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Емитување"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Луѓето во ваша близина со компатибилни уреди со Bluetooth може да ги слушаат аудиозаписите што ги емитувате"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Екранов ќе се исклучи"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Преклопувачки уред се отклопува"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Преклопувачки уред се врти"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Слаба батерија на пенкало"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index de13c2b..88a3514 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"താഴെയുള്ള അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ഇടത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"വലത് വശത്തെ അതിർത്തി <xliff:g id="PERCENT">%1$d</xliff:g> ശതമാനം"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ഔദ്യോഗിക പ്രൊഫൈലിന്റെ സ്ക്രീന്ഷോട്ടുകൾ <xliff:g id="APP">%1$s</xliff:g> ആപ്പിൽ സംരക്ഷിച്ചു"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ഫയലുകൾ"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"സ്ക്രീൻ റെക്കോർഡർ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ഇടത്തരം"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ചെറുത്"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"വലുത്"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"അടയ്ക്കുക"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"എഡിറ്റ് ചെയ്യുക"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"മാഗ്നിഫയർ വിൻഡോ ക്രമീകരണം"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ഉപയോഗസഹായി ഫീച്ചർ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ക്രമീകരണത്തിൽ ഈ ബട്ടൺ ഇഷ്ടാനുസൃതമാക്കാം, മാറ്റാം.\n\n"<annotation id="link">"ക്രമീകരണം കാണൂ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"തൽക്കാലം മറയ്ക്കുന്നതിന് ബട്ടൺ അരുകിലേക്ക് നീക്കുക"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"പഴയപടിയാക്കുക"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> കുറുക്കുവഴി നീക്കം ചെയ്തു"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# കുറുക്കുവഴി നീക്കം ചെയ്തു}other{# കുറുക്കുവഴികൾ നീക്കം ചെയ്തു}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"മുകളിൽ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"മുകളിൽ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ചുവടെ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> എന്ന ഗാനം <xliff:g id="APP_LABEL">%2$s</xliff:g> ആപ്പിൽ പ്ലേ ചെയ്യുക"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"പഴയപടിയാക്കുക"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യാൻ അടുത്തേക്ക് നീക്കുക"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ഇവിടെ പ്ലേ ചെയ്യാൻ <xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിന് അടുത്തേക്ക് നീക്കുക"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യുന്നു"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"എന്തോ കുഴപ്പമുണ്ടായി. വീണ്ടും ശ്രമിക്കുക."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ലോഡ് ചെയ്യുന്നു"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"ടാബ്ലെറ്റ്"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"വോളിയം"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"സ്പീക്കറുകളും ഡിസ്പ്ലേകളും"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"നിർദ്ദേശിച്ച ഉപകരണങ്ങൾ"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ബ്രോഡ്കാസ്റ്റ് എങ്ങനെയാണ് പ്രവർത്തിക്കുന്നത്"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ബ്രോഡ്കാസ്റ്റ്"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"അനുയോജ്യമായ Bluetooth ഉപകരണങ്ങളോടെ സമീപമുള്ള ആളുകൾക്ക് നിങ്ങൾ ബ്രോഡ്കാസ്റ്റ് ചെയ്യുന്ന മീഡിയ കേൾക്കാനാകും"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ഈ സ്ക്രീൻ ഓഫാകും"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം അൺഫോൾഡ് ആകുന്നു"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ഫോൾഡ് ചെയ്യാവുന്ന ഉപകരണം, കറങ്ങുന്ന വിധത്തിൽ ഫ്ലിപ്പ് ആകുന്നു"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"സ്റ്റൈലസിന്റെ ബാറ്ററി ചാർജ് കുറവാണ്"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 7c26813..8358164 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Доод талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зүүн талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Баруун талын хязгаар <xliff:g id="PERCENT">%1$d</xliff:g> хувь"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Дэлгэцийн үйлдэл бичигч"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Дунд зэрэг"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Жижиг"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Том"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Хаах"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Засах"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Томруулагчийн цонхны тохиргоо"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Хандалтын онцлогуудыг нээхийн тулд товшино уу. Энэ товчлуурыг Тохиргоо хэсэгт өөрчилж эсвэл солиорой.\n\n"<annotation id="link">"Тохиргоог харах"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Үүнийг түр нуухын тулд товчлуурыг зах руу зөөнө үү"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Болих"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-н товчлолыг хассан"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# товчлолыг хассан}other{# товчлолыг хассан}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Зүүн дээш зөөх"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Баруун дээш зөөх"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Зүүн доош зөөх"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g>-г <xliff:g id="APP_LABEL">%2$s</xliff:g> дээр тоглуулах"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Болих"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> дээр тоглуулахын тулд төхөөрөмжөө ойртуулна уу"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Энд тоглуулахын тулд <xliff:g id="DEVICENAME">%1$s</xliff:g>-д ойртоно уу"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> дээр тоглуулж байна"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Алдаа гарлаа. Дахин оролдоно уу."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Ачаалж байна"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Дууны түвшин"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Чанга яригч ба дэлгэц"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Нэвтрүүлэлт хэрхэн ажилладаг вэ?"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Нэвтрүүлэлт"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Тохиромжтой Bluetooth төхөөрөмжүүдтэй таны ойролцоох хүмүүс таны нэвтрүүлж буй медиаг сонсох боломжтой"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Энэ дэлгэц унтарна"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Эвхэгддэг төхөөрөмжийг дэлгэж байна"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Эвхэгддэг төхөөрөмжийг хөнтөрч байна"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Мэдрэгч үзэгний батарей бага байна"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 269a677..caf0b0a 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"खालील सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"डाव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"उजव्या सीमेपासून <xliff:g id="PERCENT">%1$d</xliff:g> टक्के"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रीन रेकॉर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्यम"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"लहान"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"मोठा"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"बंद करा"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"संपादित करा"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"मॅग्निफायर विंडो सेटिंग्ज"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"अॅक्सेसिबिलिटी वैशिष्ट्ये उघडण्यासाठी, टॅप करा. सेटिंग्जमध्ये हे बटण कस्टमाइझ करा किंवा बदला.\n\n"<annotation id="link">"सेटिंग्ज पहा"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्यामध्ये हलवा"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"पहिल्यासारखे करा"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> शॉर्टकट काढून टाकला"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# शॉर्टकट काढून टाकला}other{# शॉर्टकट काढून टाकले}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"वर डावीकडे हलवा"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"वर उजवीकडे हलवा"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"तळाशी डावीकडे हलवा"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> मध्ये <xliff:g id="SONG_NAME">%1$s</xliff:g> प्ले करा"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"पहिल्यासारखे करा"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> वर प्ले करण्यासाठी जवळ जा"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"येथे प्ले करण्यासाठी <xliff:g id="DEVICENAME">%1$s</xliff:g> च्या जवळ जा"</string>
- <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> वर प्ले केला जात आहे"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
+ <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> वर प्ले होत आहे"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"काहीतरी चूक झाली. पुन्हा प्रयत्न करा."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"लोड करत आहे"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"आढळले नाही"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"व्हॉल्यूम"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"स्पीकर आणि डिस्प्ले"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ब्रॉडकास्टिंग कसे काम करते"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ब्रॉडकास्ट करा"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कंपॅटिबल ब्लूटूथ डिव्हाइस असलेले तुमच्या जवळपासचे लोक हे तुम्ही ब्रॉडकास्ट करत असलेला मीडिया ऐकू शकतात"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ही स्क्रीन बंद होईल"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड करता येण्यासारखे डिव्हाइस अनफोल्ड केले जात आहे"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड करता येण्यासारखे डिव्हाइस आजूबाजूला फ्लिप केले जात आहे"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"स्टायलस बॅटरी कमी आहे"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 3ded5d5..4800990 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Sempadan bawah <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sempadan kiri <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sempadan kanan <xliff:g id="PERCENT">%1$d</xliff:g> peratus"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Perakam Skrin"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Sederhana"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Kecil"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Besar"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Tutup"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Tetapan tetingkap penggadang"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ketik untuk membuka ciri kebolehaksesan. Sesuaikan/gantikan butang ini dalam Tetapan.\n\n"<annotation id="link">"Lihat tetapan"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Gerakkan butang ke tepi untuk disembunyikan buat sementara waktu"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Buat asal"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pintasan <xliff:g id="FEATURE_NAME">%s</xliff:g> dialih keluar"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pintasan dialih keluar}other{# pintasan dialih keluar}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Alihkan ke atas sebelah kiri"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Alihkan ke atas sebelah kanan"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Alihkan ke bawah sebelah kiri"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Mainkan <xliff:g id="SONG_NAME">%1$s</xliff:g> daripada <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Buat asal"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Alihkan lebih dekat untuk bermain pada<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Dekatkan dengan <xliff:g id="DEVICENAME">%1$s</xliff:g> untuk bermain di sini"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Dimainkan pada <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kesilapan telah berlaku. Cuba lagi."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Memuatkan"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Kelantangan"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Pembesar Suara & Paparan"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cara siaran berfungsi"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Siarkan"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Orang berdekatan anda dengan peranti Bluetooth yang serasi boleh mendengar media yang sedang anda siarkan"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrin ini akan dimatikan"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Peranti boleh lipat dibuka"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Peranti boleh lipat diterbalikkan"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateri stilus lemah"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 9e375340..54eb158 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"အောက်ခြေအနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ဘယ်ဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ညာဘက်အနားသတ် <xliff:g id="PERCENT">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"အလတ်"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"အသေး"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"အကြီး"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ပိတ်ရန်"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ပြင်ရန်"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"မှန်ဘီလူးဝင်းဒိုး ဆက်တင်များ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုများ ဖွင့်ရန် တို့ပါ။ ဆက်တင်များတွင် ဤခလုတ်ကို စိတ်ကြိုက်ပြင်ပါ (သို့) လဲပါ။\n\n"<annotation id="link">"ဆက်တင်များ ကြည့်ရန်"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ခလုတ်ကို ယာယီဝှက်ရန် အစွန်းသို့ရွှေ့ပါ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"နောက်ပြန်ရန်"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ဖြတ်လမ်းလင့်ခ် ဖယ်ရှားထားသည်"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{ဖြတ်လမ်းလင့်ခ် # ခု ဖယ်ရှားထားသည်}other{ဖြတ်လမ်းလင့်ခ် # ခု ဖယ်ရှားထားသည်}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ဘယ်ဘက်ထိပ်သို့ ရွှေ့ရန်"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ညာဘက်ထိပ်သို့ ရွှေ့ရန်"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ဘယ်ဘက်အောက်ခြေသို့ ရွှေ့ရန်"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> ကို <xliff:g id="APP_LABEL">%2$s</xliff:g> တွင် ဖွင့်ပါ"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"နောက်ပြန်ရန်"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> တွင်ဖွင့်ရန် အနီးသို့ရွှေ့ပါ"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ဤနေရာတွင်ဖွင့်ရန် <xliff:g id="DEVICENAME">%1$s</xliff:g> အနီးသို့တိုးပါ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> တွင် ဖွင့်နေသည်"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"တစ်ခုခုမှားသွားသည်။ ထပ်စမ်းကြည့်ပါ။"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ဖွင့်နေသည်"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"မတွေ့ပါ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"အသံအတိုးအကျယ်"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"စပီကာနှင့် ဖန်သားပြင်များ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ထုတ်လွှင့်မှုဆောင်ရွက်ပုံ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ထုတ်လွှင့်ခြင်း"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"အနီးရှိတွဲသုံးနိုင်သော ဘလူးတုသ်သုံးစက် အသုံးပြုသူများက သင်ထုတ်လွှင့်နေသော မီဒီယာကို နားဆင်နိုင်သည်"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ဤဖန်သားပြင်ကို ပိတ်လိုက်မည်"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ခေါက်နိုင်သောစက်ကို ဖြန့်လိုက်သည်"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ခေါက်နိုင်သောစက်ကို တစ်ဘက်သို့ လှန်လိုက်သည်"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"စတိုင်လပ်စ် ဘက်ထရီ အားနည်းနေသည်"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ba1aa91..70dc961 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nedre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Venstre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Høyre grense <xliff:g id="PERCENT">%1$d</xliff:g> prosent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Skjermopptaker"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Middels"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Liten"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Stor"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Lukk"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Endre"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Innstillinger for forstørringsvindu"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Trykk for å åpne tilgj.funksjoner. Tilpass eller bytt knappen i Innstillinger.\n\n"<annotation id="link">"Se innstillingene"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytt knappen til kanten for å skjule den midlertidig"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Angre"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-snarveien er fjernet"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# snarvei er fjernet}other{# snarveier er fjernet}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytt til øverst til venstre"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flytt til øverst til høyre"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Flytt til nederst til venstre"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> fra <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Angre"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Flytt nærmere for å spille av på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Flytt deg nærmere <xliff:g id="DEVICENAME">%1$s</xliff:g> for å spille av her"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Spilles av på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Noe gikk galt. Prøv på nytt."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Laster inn"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Høyttalere og skjermer"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Slik fungerer kringkasting"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Kringkasting"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Folk i nærheten med kompatible Bluetooth-enheter kan lytte til mediene du kringkaster"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Denne skjermen slås av"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En sammenleggbar enhet blir brettet ut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En sammenleggbar enhet blir snudd"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Det er lite batteri i pekepennen"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c0221f6..1aa4e43 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"फेदबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"बायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"दायाँ किनाराबाट <xliff:g id="PERCENT">%1$d</xliff:g> प्रतिशत"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"स्क्रिन रेकर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"मध्यम"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"सानो"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ठुलो"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"बन्द गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"सम्पादन गर्नुहोस्"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"म्याग्निफायर विन्डोसम्बन्धी सेटिङ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"सर्वसुलभता कायम गर्ने सुविधा खोल्न ट्याप गर्नुहोस्। सेटिङमा गई यो बटन कस्टमाइज गर्नुहोस् वा बदल्नुहोस्।\n\n"<annotation id="link">"सेटिङ हेर्नुहोस्"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"यो बटन केही बेर नदेखिने पार्न किनारातिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"अन्डू गर्नुहोस्"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> सर्टकट हटाइएको छ"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# सर्टकट हटाइएको छ}other{# वटा सर्टकट हटाइएका छन्}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सिरानको बायाँतिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"सिरानको दायाँतिर सार्नुहोस्"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"पुछारको बायाँतिर सार्नुहोस्"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> बोलको गीत <xliff:g id="APP_LABEL">%2$s</xliff:g> मा बजाउनुहोस्"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"अन्डू गर्नुहोस्"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> मा प्ले गर्न आफ्नो डिभाइस नजिकै लैजानुहोस्"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"तपाईं यहाँ प्ले गर्न चाहनुहुन्छ भने आफ्नो डिभाइसलाई <xliff:g id="DEVICENAME">%1$s</xliff:g> नजिकै लैजानुहोस्"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> मा प्ले गरिँदै छ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"केही चिज गडबड भयो। फेरि प्रयास गर्नुहोस्।"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"लोड हुँदै छ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"फेला परेन"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"भोल्युम"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"स्पिकर तथा डिस्प्लेहरू"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"प्रसारण गर्ने सुविधाले कसरी काम गर्छ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"प्रसारण"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"कम्प्याटिबल ब्लुटुथ डिभाइस भएका नजिकैका मान्छेहरू तपाईंले प्रसारण गरिरहनुभएको मिडिया सुन्न सक्छन्"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ यो स्क्रिन अफ हुने छ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"फोल्ड गर्न मिल्ने डिभाइस अनफोल्ड गरेको देखाइएको एनिमेसन"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"फोल्ड गर्न मिल्ने डिभाइस यताउता पल्टाएर देखाइएको एनिमेसन"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"स्टाइलसको ब्याट्री लो छ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index d8ce030..9aaa56d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Ondergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Linkergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Rechtergrens <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Schermopname"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Normaal"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Klein"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Groot"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Sluiten"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Bewerken"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Instellingen voor vergrotingsvenster"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tik voor toegankelijkheidsfuncties. Wijzig of vervang deze knop via Instellingen.\n\n"<annotation id="link">"Naar Instellingen"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Knop naar de rand verplaatsen om deze tijdelijk te verbergen"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ongedaan maken"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Snelkoppeling voor <xliff:g id="FEATURE_NAME">%s</xliff:g> verwijderd"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# snelkoppeling verwijderd}other{# snelkoppelingen verwijderd}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Naar linksboven verplaatsen"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Naar rechtsboven verplaatsen"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Naar linksonder verplaatsen"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> van <xliff:g id="ARTIST_NAME">%2$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> afspelen via <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Ongedaan maken"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ga dichter naar <xliff:g id="DEVICENAME">%1$s</xliff:g> toe om af te spelen"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ga dichter bij <xliff:g id="DEVICENAME">%1$s</xliff:g> staan om hier af te spelen"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Houd dichter bij <xliff:g id="DEVICENAME">%1$s</xliff:g> om af te spelen"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Afspelen op <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Er is iets misgegaan. Probeer het opnieuw."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Laden"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Speakers en schermen"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Hoe uitzenden werkt"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Uitzending"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Mensen bij jou in de buurt met geschikte bluetooth-apparaten kunnen luisteren naar de media die je uitzendt"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Dit scherm gaat uit"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Opvouwbaar apparaat wordt uitgevouwen"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Opvouwbaar apparaat wordt gedraaid"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Batterij van stylus bijna leeg"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 48771b3..d7c17a2 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ନିମ୍ନ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ବାମ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ଡାହାଣ ସୀମାରେଖା <xliff:g id="PERCENT">%1$d</xliff:g> ଶତକଡ଼ା"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ସ୍କ୍ରିନ୍ ରେକର୍ଡର୍"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରିନ୍ ରେକର୍ଡ୍ ସେସନ୍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ମଧ୍ୟମ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ଛୋଟ"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ବଡ଼"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ବନ୍ଦ କରନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ଏଡିଟ କରନ୍ତୁ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ମ୍ୟାଗ୍ନିଫାୟର ୱିଣ୍ଡୋର ସେଟିଂସ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚର ଖୋଲିବାକୁ ଟାପ କରନ୍ତୁ। ସେଟିଂସରେ ଏହି ବଟନକୁ କଷ୍ଟମାଇଜ କର କିମ୍ବା ବଦଳାଅ।\n\n"<annotation id="link">"ସେଟିଂସ ଦେଖନ୍ତୁ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ବଟନକୁ ଅସ୍ଥାୟୀ ଭାବେ ଲୁଚାଇବା ପାଇଁ ଏହାକୁ ଗୋଟିଏ ଧାରକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ପୂର୍ବବତ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}other{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ଶୀର୍ଷ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ଶୀର୍ଷ ଡାହାଣକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ନିମ୍ନ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g>ରୁ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ପୂର୍ବବତ୍ କରନ୍ତୁ"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ଚଲାଇବା ପାଇଁ ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ଏଠାରେ ଚଲାଇବା ପାଇଁ <xliff:g id="DEVICENAME">%1$s</xliff:g>ର ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
- <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ଚାଲୁଛି"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ପ୍ଲେ କରିବା ପାଇଁ ପାଖକୁ ମୁଭ କରନ୍ତୁ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
+ <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>ରେ ପ୍ଲେ ହେଉଛି"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"କିଛି ତ୍ରୁଟି ହୋଇଛି। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ଲୋଡ ହେଉଛି"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ମିଳିଲା ନାହିଁ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ଭଲ୍ୟୁମ"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ସ୍ପିକର ଏବଂ ଡିସପ୍ଲେଗୁଡ଼ିକ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ବ୍ରଡକାଷ୍ଟିଂ କିପରି କାମ କରେ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ବ୍ରଡକାଷ୍ଟ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ଆପଣଙ୍କ ଆଖପାଖର କମ୍ପାଟିବଲ ବ୍ଲୁଟୁଥ ଡିଭାଇସ ଥିବା ଲୋକମାନେ ଆପଣ ବ୍ରଡକାଷ୍ଟ କରୁଥିବା ମିଡିଆ ଶୁଣିପାରିବେ"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ଏହି ସ୍କ୍ରିନ ବନ୍ଦ ହୋଇଯିବ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରାଯାଉଛି"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ଫୋଲ୍ଡ କରାଯାଇପାରୁଥିବା ଡିଭାଇସକୁ ଫ୍ଲିପ କରାଯାଉଛି"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ଷ୍ଟାଇଲସ ବେଟେରୀର ଚାର୍ଜ କମ ଅଛି"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 8161613..a6fd6eb 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ਹੇਠਾਂ ਦੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ਖੱਬੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ਸੱਜੇ ਪਾਸੇ ਵਾਲੀ ਸੀਮਾ <xliff:g id="PERCENT">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ਦਰਮਿਆਨਾ"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"ਛੋਟਾ"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ਵੱਡਾ"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ਬੰਦ ਕਰੋ"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"ਵੱਡਦਰਸ਼ੀ ਵਿੰਡੋ ਸੈਟਿੰਗਾਂ"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ। ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਹ ਬਟਨ ਵਿਉਂਤਬੱਧ ਕਰੋ ਜਾਂ ਬਦਲੋ।\n\n"<annotation id="link">"ਸੈਟਿੰਗਾਂ ਦੇਖੋ"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ਬਟਨ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਲੁਕਾਉਣ ਲਈ ਕਿਨਾਰੇ \'ਤੇ ਲਿਜਾਓ"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"ਅਣਕੀਤਾ ਕਰੋ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}one{# ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}other{# ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ਉੱਪਰ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ਉੱਪਰ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ਹੇਠਾਂ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ਤੋਂ <xliff:g id="SONG_NAME">%1$s</xliff:g> ਚਲਾਓ"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"ਅਣਕੀਤਾ ਕਰੋ"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> \'ਤੇ ਚਲਾਉਣ ਲਈ ਨੇੜੇ ਲਿਜਾਓ"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ਇੱਥੇ ਚਲਾਉਣ ਲਈ <xliff:g id="DEVICENAME">%1$s</xliff:g> ਦੇ ਨੇੜੇ ਜਾਓ"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> \'ਤੇ ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"ਨਹੀਂ ਮਿਲਿਆ"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ਅਵਾਜ਼"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ਸਪੀਕਰ ਅਤੇ ਡਿਸਪਲੇਆਂ"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ਪ੍ਰਸਾਰਨ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ਪ੍ਰਸਾਰਨ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ਅਨੁਰੂਪ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਨਾਲ ਨਜ਼ਦੀਕੀ ਲੋਕ ਤੁਹਾਡੇ ਵੱਲੋਂ ਪ੍ਰਸਾਰਨ ਕੀਤੇ ਜਾ ਰਹੇ ਮੀਡੀਆ ਨੂੰ ਸੁਣ ਸਕਦੇ ਹਨ"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ਇਹ ਸਕ੍ਰੀਨ ਬੰਦ ਹੋ ਜਾਵੇਗੀ"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"ਮੋੜਨਯੋਗ ਡੀਵਾਈਸ ਨੂੰ ਆਲੇ-ਦੁਆਲੇ ਫਲਿੱਪ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ਸਟਾਈਲਸ ਦੀ ਬੈਟਰੀ ਘੱਟ ਹੈ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 09a0e24..592c334 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Przycięcie dolnej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Przycięcie lewej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Przycięcie prawej krawędzi o <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Nagrywanie ekranu"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
@@ -388,7 +392,7 @@
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
<string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Podczas udostępniania, nagrywania lub przesyłania treści aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Dalej"</string>
- <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Udostępnianie i nagrywanie za pomocą aplikacji"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Udostępnianie i nagrywanie aplikacji"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Zezwolić tej aplikacji na udostępnianie lub nagrywanie?"</string>
<string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Podczas udostępniania, nagrywania lub przesyłania treści ta aplikacja ma dostęp do wszystkiego, co jest widoczne na ekranie lub odtwarzane na urządzeniu. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
<string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Podczas udostępniania, nagrywania lub przesyłania treści ta aplikacja ma dostęp do wszystkiego, co jest w niej wyświetlane lub odtwarzane. Zachowaj ostrożność w przypadku haseł, danych do płatności, wiadomości i innych informacji poufnych."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Średni"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Mały"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Duży"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zamknij"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Edytuj"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Ustawienia okna powiększania"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Kliknij, aby otworzyć ułatwienia dostępu. Dostosuj lub zmień ten przycisk w Ustawieniach.\n\n"<annotation id="link">"Wyświetl ustawienia"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Przesuń przycisk do krawędzi, aby ukryć go tymczasowo"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Cofnij"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> – skrót został usunięty"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# skrót został usunięty}few{# skróty zostały usunięte}many{# skrótów zostało usuniętych}other{# skrótu zostało usunięte}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Przenieś w lewy górny róg"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Przenieś w prawy górny róg"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Przenieś w lewy dolny róg"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Odtwórz utwór <xliff:g id="SONG_NAME">%1$s</xliff:g> w aplikacji <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Cofnij"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Przysuń się bliżej, aby odtwarzać na urządzeniu <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Zbliż do urządzenia <xliff:g id="DEVICENAME">%1$s</xliff:g>, aby na nim odtwarzać"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Odtwarzam na ekranie <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Coś poszło nie tak. Spróbuj ponownie."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Wczytuję"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Głośność"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Głośniki i wyświetlacze"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jak działa transmitowanie"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmisja"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osoby w pobliżu ze zgodnymi urządzeniami Bluetooth mogą słuchać transmitowanych przez Ciebie multimediów"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"* Ekran się wyłączy"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Składane urządzenie jest rozkładane"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Składane urządzenie jest obracane"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Słaba bateria w rysiku"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index cf0839f..c35a7f8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Borda inferior em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Capturas de tela do trabalho são salvas no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -461,7 +463,7 @@
<string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ele é mantido à vista até que seja liberado. Deslize para cima e mantenha pressionado para liberar."</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ele é mantido à vista até que seja liberado. Deslize para cima pressione para liberar."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Ela é mantida à vista até que seja liberada. Toque em Início e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Dados pessoais podem ficar acessíveis (como contatos e conteúdo de e-mail)."</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeno"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Fechar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configurações da janela de lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir os recursos de acessibilidade. Personalize ou substitua o botão nas Configurações.\n\n"<annotation id="link">"Ver configurações"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfazer"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}one{# atalho removido}many{# de atalhos removidos}other{# atalhos removidos}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover para o canto superior direito"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover para o canto inferior esquerdo"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Desfazer"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime os dispositivos para tocar a mídia neste: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para abrir a mídia aqui"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Mídia aberta no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo deu errado. Tente novamente."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Carregando"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ece5eb6..f483ef7 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Limite inferior de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Limite esquerdo de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Limite direito de <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"As capturas de ecrã do trabalho são guardadas na app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Ficheiros"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Gravador de ecrã"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeno"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Fechar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Definições da janela da lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir funcionalidades de acessibilidade. Personal. ou substitua botão em Defin.\n\n"<annotation id="link">"Ver defin."</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a extremidade para o ocultar temporariamente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anular"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}many{# atalhos removidos}other{# atalhos removidos}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover p/ parte sup. esquerda"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover parte superior direita"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover p/ parte infer. esquerda"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Reproduzir <xliff:g id="SONG_NAME">%1$s</xliff:g> a partir da app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Anular"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime-se para reproduzir no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para reproduzir aqui"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"A reproduzir no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo correu mal. Tente novamente."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"A carregar"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controlo está indisponível"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altifalantes e ecrãs"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmissão"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas de si com dispositivos Bluetooth compatíveis podem ouvir o conteúdo multimédia que está a transmitir"</string>
@@ -1053,5 +1056,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Este ecrã vai ser desligado"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável a ser desdobrado"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável a ser virado ao contrário"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da caneta stylus fraca"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> de bateria restante"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Ligue a caneta stylus a um carregador"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index cf0839f..c35a7f8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Borda inferior em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Borda esquerda em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Borda direita em <xliff:g id="PERCENT">%1$d</xliff:g> por cento"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Capturas de tela do trabalho são salvas no app <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Files"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Gravador de tela"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -461,7 +463,7 @@
<string name="screen_pinning_title" msgid="9058007390337841305">"O app está fixado"</string>
<string name="screen_pinning_description" msgid="8699395373875667743">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Visão geral e mantenha essas opções pressionadas para liberar."</string>
<string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ela é mantida à vista até que seja liberada. Toque em Voltar e em Início e mantenha essas opções pressionadas para liberar."</string>
- <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ele é mantido à vista até que seja liberado. Deslize para cima e mantenha pressionado para liberar."</string>
+ <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"Ele é mantido à vista até que seja liberado. Deslize para cima pressione para liberar."</string>
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ela é mantida à vista até que seja liberada. Toque em Visão geral e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Ela é mantida à vista até que seja liberada. Toque em Início e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Dados pessoais podem ficar acessíveis (como contatos e conteúdo de e-mail)."</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Médio"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Pequeno"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Grande"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Fechar"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editar"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Configurações da janela de lupa"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir os recursos de acessibilidade. Personalize ou substitua o botão nas Configurações.\n\n"<annotation id="link">"Ver configurações"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfazer"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}one{# atalho removido}many{# de atalhos removidos}other{# atalhos removidos}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mover para o canto superior direito"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mover para o canto inferior esquerdo"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Tocar <xliff:g id="SONG_NAME">%1$s</xliff:g> no app <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Desfazer"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Aproxime os dispositivos para tocar a mídia neste: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Aproxime-se do dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g> para abrir a mídia aqui"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Mídia aberta no dispositivo <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Algo deu errado. Tente novamente."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Carregando"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Alto-falantes e telas"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Dispositivos sugeridos"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Como funciona a transmissão"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmitir"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"As pessoas próximas a você com dispositivos Bluetooth compatíveis podem ouvir a mídia que você está transmitindo"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Esta tela vai ser desativada"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispositivo dobrável sendo aberto"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispositivo dobrável sendo virado"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria da stylus fraca"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b4bb0c4..9196f47 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Marginea de jos la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Marginea stângă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Marginea dreaptă la <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Recorder pentru ecran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mediu"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Mic"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Mare"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Închide"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Editează"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Setările ferestrei de mărire"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Atinge ca să deschizi funcțiile de accesibilitate. Personalizează sau înlocuiește butonul în setări.\n\n"<annotation id="link">"Vezi setările"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mută butonul spre margine pentru a-l ascunde temporar"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anulează"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Comandă rapidă <xliff:g id="FEATURE_NAME">%s</xliff:g> eliminată"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# comandă rapidă eliminată}few{# comenzi rapide eliminate}other{# de comenzi rapide eliminate}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mută în stânga sus"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Mută în dreapta sus"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Mută în stânga jos"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Redă <xliff:g id="SONG_NAME">%1$s</xliff:g> în <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Anulează"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Apropie-te pentru a reda pe <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Apropie-te de <xliff:g id="DEVICENAME">%1$s</xliff:g> ca să redai acolo"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Se redă pe <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"A apărut o eroare. Încearcă din nou."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Se încarcă"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verifică aplicația"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volum"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Difuzoare și afișaje"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cum funcționează transmisia"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmite"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Persoanele din apropiere cu dispozitive Bluetooth compatibile pot asculta conținutul pe care îl transmiți"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Acest ecran se va dezactiva"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Dispozitiv pliabil care este desfăcut"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Dispozitiv pliabil care este întors"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Nivelul bateriei creionului este scăzut"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9dc0389..804f9af 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Граница снизу: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Граница слева: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Граница справа: <xliff:g id="PERCENT">%1$d</xliff:g> %%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Запись видео с экрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средняя"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Маленькая"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Большая"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Закрыть"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Изменить"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Настройка окна лупы"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Нажмите, чтобы открыть спец. возможности. Настройте или замените эту кнопку в настройках.\n\n"<annotation id="link">"Настройки"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Чтобы временно скрыть кнопку, переместите ее к краю экрана"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Отменить"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>: сочетание клавиш удалено"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# сочетание клавиш удалено}one{# сочетание клавиш удалено}few{# сочетания клавиш удалено}many{# сочетаний клавиш удалено}other{# сочетания клавиш удалено}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перенести в левый верхний угол"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перенести в правый верхний угол"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Перенести в левый нижний угол"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Воспроизвести медиафайл \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" из приложения \"<xliff:g id="APP_LABEL">%2$s</xliff:g>\""</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Отменить"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Чтобы начать трансляцию на устройстве \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\", подойдите к нему ближе."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Для воспроизведения на этом устройстве подойдите ближе к другому (<xliff:g id="DEVICENAME">%1$s</xliff:g>)."</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Воспроизводится на устройстве \"<xliff:g id="DEVICENAME">%1$s</xliff:g>\"."</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Произошла ошибка. Повторите попытку."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Загрузка…"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не найдено."</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Громкость"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Колонки и дисплеи"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Как работают трансляции"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Трансляция"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Находящиеся рядом с вами люди с совместимыми устройствами Bluetooth могут слушать медиафайлы, которые вы транслируете."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Этот экран отключится"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Складное устройство в разложенном виде"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Перевернутое складное устройство"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Низкий заряд батареи стилуса"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 635b059..518d184 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"පහළ සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"වම් සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"දකුණු සීමාව සියයට <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"තිර රෙකෝඩරය"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"මධ්යම"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"කුඩා"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"විශාල"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"වසන්න"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"සංස්කරණය කරන්න"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"විශාලන කවුළු සැකසීම්"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ප්රවේශ්යතා විශේෂාංග විවෘත කිරීමට තට්ටු කරන්න. සැකසීම් තුළ මෙම බොත්තම අභිරුචිකරණය හෝ ප්රතිස්ථාපනය කරන්න.\n\n"<annotation id="link">"සැකසීම් බලන්න"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"එය තාවකාලිකව සැඟවීමට බොත්තම දාරයට ගෙන යන්න"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"අස් කරන්න"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> කෙටිමඟ ඉවත් කළා"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# කෙටිමඟක් ඉවත් කළා}one{කෙටිමං #ක් ඉවත් කළා}other{කෙටිමං #ක් ඉවත් කළා}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ඉහළ වමට ගෙන යන්න"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ඉහළ දකුණට ගෙන යන්න"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"පහළ වමට ගෙන යන්න"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%2$s</xliff:g> වෙතින් වාදනය කරන්න"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"පසුගමනය කරන්න"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> හි වාදනය කිරීමට වඩාත් ළං වන්න"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"මෙහි ක්රීඩා කිරීමට <xliff:g id="DEVICENAME">%1$s</xliff:g> වෙත වඩා සමීප වන්න"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> හි වාදනය කරමින්"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"යම් දෙයක් වැරදිණි. නැවත උත්සාහ කරන්න."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"පූරණය වේ"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"අක්රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"හඬ පරිමාව"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ස්පීකර් සහ සංදර්ශක"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"විකාශනය ක්රියා කරන ආකාරය"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"විකාශනය"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ගැළපෙන බ්ලූටූත් උපාංග සහිත ඔබ අවට සිටින පුද්ගලයින්ට ඔබ විකාශනය කරන මාධ්යයට සවන් දිය හැකිය"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ මෙම තිරය ක්රියා විරහිත වනු ඇත"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"දිග හැරෙමින් පවතින නැමිය හැකි උපාංගය"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"වටා පෙරළෙමින් තිබෙන නැමිය හැකි උපාංගය"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"පන්හිඳ බැටරිය අඩුයි"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2c59f49..7dc85b8 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> %% dolnej hranice"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> %% ľavej hranice"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> %% pravej hranice"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Rekordér obrazovky"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
@@ -386,9 +390,9 @@
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Celá obrazovka"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Jedna aplikácia"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Počas zdieľania, nahrávania alebo prenosu bude mať <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému na obrazovke, prípadne k obsahu, ktorý sa bude v zariadení prehrávať. Preto venujte zvýšenú pozornosť heslám, platobným údajom, správam a ďalším citlivým údajom."</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Počas zdieľania, nahrávania alebo prenosu bude mať aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> prístup k všetkému obsahu, ktorý sa v nej bude zobrazovať alebo prehrávať. Preto venujte zvýšenú pozornosť heslám, platobným údajom, správam a ďalším citlivým údajom."</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Keď zdieľate, nahrávate alebo prenášate nejakú aplikáciu, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> má prístup k všetkému obsahu, ktorý sa v aplikácii zobrazuje alebo prehráva. Dajte preto pozor na heslá, platobné údaje, osobné správy a iné citlivé údaje."</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"Pokračovať"</string>
- <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Aplikácia na zdieľanie alebo nahrávanie"</string>
+ <string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"Vyberte aplikáciu, ktorú chcete zdieľať alebo nahrávať"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"Chcete povoliť tejto aplikácii zdieľať alebo nahrávať?"</string>
<string name="media_projection_permission_dialog_system_service_warning_entire_screen" msgid="8801616203805837575">"Počas zdieľania, nahrávania alebo prenosu bude mať táto aplikácia prístup k všetkému na obrazovke, prípadne k obsahu, ktorý sa bude v zariadení prehrávať. Venujte preto zvýšenú pozornosť heslám, platobným údajom, správam a ďalším citlivým údajom."</string>
<string name="media_projection_permission_dialog_system_service_warning_single_app" msgid="543310680568419338">"Počas zdieľania, nahrávania alebo prenosu bude mať táto aplikácia prístup k všetkému obsahu, ktorý sa v nej bude zobrazovať alebo prehrávať. Venujte preto zvýšenú pozornosť heslám, platobným údajom, správam či ďalším citlivým údajom."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Stredný"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Malý"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Veľký"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zavrieť"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Upraviť"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Nastavenia okna lupy"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Funkcie dostupnosti otvoríte klepnutím. Tlačidlo prispôsobte alebo nahraďte v Nastav.\n\n"<annotation id="link">"Zobraz. nast."</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ak chcete tlačidlo dočasne skryť, presuňte ho k okraju"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Späť"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Bola odstránená skratka <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Bola odstránená # skratka}few{Boli odstránené # skratky}many{# shortcuts removed}other{Bolo odstránených # skratiek}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Presunúť doľava nahor"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Presunúť doprava nahor"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Presunúť doľava nadol"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> od interpreta <xliff:g id="ARTIST_NAME">%2$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Prehrať skladbu <xliff:g id="SONG_NAME">%1$s</xliff:g> z aplikácie <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Späť"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ak chcete prehrávať v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>, priblížte sa"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Ak chcete prehrávať v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>, priblížte sa k nemu"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Ak chcete prehrávať v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>, priblížte sa k nemu"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Prehráva sa v zariadení <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Niečo sa pokazilo. Skúste to znova."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Načítava sa"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Hlasitosť"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Reproduktory a obrazovky"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Ako vysielanie funguje"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Vysielanie"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Ľudia v okolí s kompatibilnými zariadeniami s rozhraním Bluetooth si môžu vypočuť médiá, ktoré vysielate"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Táto obrazovka sa vypne"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Rozloženie skladacieho zariadenia"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Prevrátenie skladacieho zariadenia"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stav batérie dotykového pera je nízky"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 3830dcf..9d3c287 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Meja spodaj <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Meja levo <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Meja desno <xliff:g id="PERCENT">%1$d</xliff:g> odstotkov"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Snemalnik zaslona"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Srednja"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Majhna"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Velika"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Zapri"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Uredi"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Nastavitve okna povečevalnika"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dotaknite se za funkcije za ljudi s posebnimi potrebami. Ta gumb lahko prilagodite ali zamenjate v nastavitvah.\n\n"<annotation id="link">"Ogled nastavitev"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Če želite gumb začasno skriti, ga premaknite ob rob."</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Razveljavi"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Odstranjena bližnjica za fun. <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Odstranjena # bližnjica}one{Odstranjena # bližnjica}two{Odstranjeni # bližnjici}few{Odstranjene # bližnjice}other{Odstranjenih # bližnjic}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premakni zgoraj levo"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Premakni zgoraj desno"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Premakni spodaj levo"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> izvajalca <xliff:g id="ARTIST_NAME">%2$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%3$s</xliff:g>."</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Predvajaj skladbo <xliff:g id="SONG_NAME">%1$s</xliff:g> iz aplikacije <xliff:g id="APP_LABEL">%2$s</xliff:g>."</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Razveljavi"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Za predvajanje v napravi <xliff:g id="DEVICENAME">%1$s</xliff:g> bolj približajte telefon."</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Približajte napravi <xliff:g id="DEVICENAME">%1$s</xliff:g> za predvajanje v tej napravi"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Za predvajanje v napravi <xliff:g id="DEVICENAME">%1$s</xliff:g> bolj približajte telefon"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Predvajanje v napravi <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Prišlo je do napake. Poskusite znova."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Nalaganje"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Glasnost"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Zvočniki in zasloni"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Kako deluje oddajanje"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Oddajanje"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Osebe v bližini z združljivo napravo Bluetooth lahko poslušajo predstavnost, ki jo oddajate."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ta zaslon se bo izklopil."</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Razpiranje zložljive naprave"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Obračanje zložljive naprave"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Skoraj prazna baterija pisala"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 219704d..14438ef 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Kufiri i poshtëm <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Kufiri i majtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Kufiri i djathtë <xliff:g id="PERCENT">%1$d</xliff:g> për qind"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Regjistruesi i ekranit"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
@@ -383,7 +387,7 @@
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Do të fillosh regjistrimin ose transmetimin?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"Fillo regjistrimin ose transmetimin me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"Të lejohet <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> të shpërndajë ose regjistrojë?"</string>
- <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Ekran i plotë"</string>
+ <string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"Të gjithë ekranin"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"Vetëm një aplikacion"</string>
<string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"Gjatë shpërndarjes, regjistrimit ose transmetimit, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në pajisjen tënde. Prandaj ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
<string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"Gjatë shpërndarjes, regjistrimit ose transmetimit të një aplikacioni, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ka qasje te çdo gjë e dukshme në ekranin tënd ose që po luhet në atë aplikacion. Prandaj, ki kujdes me fjalëkalimet, detajet e pagesës, mesazhet ose informacione të tjera të ndjeshme."</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Mesatar"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"I vogël"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"I madh"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Mbyll"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Modifiko"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Cilësimet e dritares së zmadhimit"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Trokit dhe hap veçoritë e qasshmërisë. Modifiko ose ndërro butonin te \"Cilësimet\".\n\n"<annotation id="link">"Shih cilësimet"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Zhvendose butonin në skaj për ta fshehur përkohësisht"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Zhbëj"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Shkurtorja për \"<xliff:g id="FEATURE_NAME">%s</xliff:g>\" u hoq"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shkurtore u hoq}other{# shkurtore u hoqën}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Zhvendos lart majtas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Zhvendos lart djathtas"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Zhvendos poshtë majtas"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Luaj <xliff:g id="SONG_NAME">%1$s</xliff:g> nga <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Zhbëj"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Afrohu për të luajtur në <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Afrohu te <xliff:g id="DEVICENAME">%1$s</xliff:g> për ta luajtur këtu"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Po luhet në <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Ndodhi një gabim. Provo përsëri."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Po ngarkohet"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volumi"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Altoparlantët dhe ekranet"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Si funksionon transmetimi"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Transmetimi"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personat në afërsi me ty me pajisje të përputhshme me Bluetooth mund të dëgjojnë median që ti po transmeton"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Ky ekran do të fiket"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Pajisja e palosshme duke u hapur"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Pajisja e palosshme duke u rrotulluar"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bateria e stilolapsit në nivel të ulët"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index de9aa2f..e724213 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Доња ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Лева ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Десна ивица <xliff:g id="PERCENT">%1$d</xliff:g> посто"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Снимач екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Средње"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Мало"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Велико"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Затвори"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Измени"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Подешавања прозора за увећање"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Додирните за функције приступачности. Прилагодите или замените ово дугме у Подешавањима.\n\n"<annotation id="link">"Подешавања"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Померите дугме до ивице да бисте га привремено сакрили"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Опозови"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Пречица функције<xliff:g id="FEATURE_NAME">%s</xliff:g> је уклоњена"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# пречица је уклоњена}one{# пречица је уклоњена}few{# пречице су уклоњене}other{# пречица је уклоњено}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Премести горе десно"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Премести доле лево"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Пустите <xliff:g id="SONG_NAME">%1$s</xliff:g> из апликације <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Опозови"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Приближите да бисте пуштали музику на: <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Приближите се уређају <xliff:g id="DEVICENAME">%1$s</xliff:g> да бисте на њему пуштали"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Пушта се на уређају <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Дошло је до грешке. Пробајте поново."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Учитава се"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Звук"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Звучници и екрани"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Како функционише емитовање"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Емитовање"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Људи у близини са компатибилним Bluetooth уређајима могу да слушају медијски садржај који емитујете"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Овај екран ће се искључити"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Уређај на преклоп се отвара"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Уређај на преклоп се обрће"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Низак ниво батерије писаљке"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 485acc0..eeee083 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Nedre gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Vänster gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Höger gräns: <xliff:g id="PERCENT">%1$d</xliff:g> procent"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Jobbskärmbilder sparas i <xliff:g id="APP">%1$s</xliff:g>-appen"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Filer"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Skärminspelare"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Medel"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Liten"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Stor"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Stäng"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Redigera"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Inställningar för förstoringsfönster"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tryck för att öppna tillgänglighetsfunktioner. Anpassa/ersätt knappen i Inställningar.\n\n"<annotation id="link">"Inställningar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytta knappen till kanten för att dölja den tillfälligt"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ångra"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> genväg har tagits bort"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# genväg har tagits bort}other{# genvägar har tagits bort}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytta högst upp till vänster"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Flytta högst upp till höger"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Flytta längst ned till vänster"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Spela upp <xliff:g id="SONG_NAME">%1$s</xliff:g> från <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Ångra"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Flytta närmare för att spela upp på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Flytta dig närmare <xliff:g id="DEVICENAME">%1$s</xliff:g> om du vill spela här"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Spelas upp på <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Något gick fel. Försök igen."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Läser in"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"surfplatta"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Styrning är inte tillgänglig"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volym"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g> %%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Högtalare och skärmar"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Förslag på enheter"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Så fungerar utsändning"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Utsändning"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Personer i närheten med kompatibla Bluetooth-enheter kan lyssna på medieinnehåll som du sänder ut"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Den här skärmen inaktiveras"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"En vikbar enhet viks upp"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"En vikbar enhet vänds"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"E-pennans batterinivå är låg"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 16691ba..8e1067c 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Mpaka wa sehemu ya chini wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Mpaka wa sehemu ya kushoto wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Mpaka wa sehemu ya kulia wa asilimia <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Kinasa Skrini"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Wastani"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Ndogo"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Kubwa"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Funga"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Badilisha"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Mipangilio ya dirisha la kikuzaji"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Gusa ili ufungue vipengele vya ufikivu. Weka mapendeleo au ubadilishe kitufe katika Mipangilio.\n\n"<annotation id="link">"Angalia mipangilio"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sogeza kitufe kwenye ukingo ili ukifiche kwa muda"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Tendua"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Njia ya mkato ya <xliff:g id="FEATURE_NAME">%s</xliff:g> imeondolewa"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Njia # ya mkato imeondolewa}other{Njia # za mkato zimeondolewa}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sogeza juu kushoto"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sogeza juu kulia"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Sogeza chini kushoto"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> ulioimbwa na <xliff:g id="ARTIST_NAME">%2$s</xliff:g> katika <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Cheza <xliff:g id="SONG_NAME">%1$s</xliff:g> katika <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Tendua"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Sogea karibu ili ucheze kwenye <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Sogeza karibu na <xliff:g id="DEVICENAME">%1$s</xliff:g> ili kucheza hapa"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Sogeza karibu ili ucheze kwenye <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Inacheza kwenye <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Hitilafu fulani imetokea. Jaribu tena."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Inapakia"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Sauti"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Spika na Skrini"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Jinsi utangazaji unavyofanya kazi"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Tangaza"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Watu walio karibu nawe wenye vifaa oanifu vya Bluetooth wanaweza kusikiliza maudhui unayoyatangaza"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Skrini hii itajizima"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Kifaa kinachokunjwa kikikunjuliwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Kifaa kinachokunjwa kikigeuzwa"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Chaji ya betri ya Stylus imepungua"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 6c7cab5..5d78e4e 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -28,6 +28,7 @@
<!-- QS-->
<dimen name="qs_panel_padding_top">16dp</dimen>
+ <dimen name="qs_panel_padding">24dp</dimen>
<dimen name="qs_content_horizontal_padding">24dp</dimen>
<dimen name="qs_horizontal_margin">24dp</dimen>
<!-- in split shade qs_tiles_page_horizontal_margin should be equal of qs_horizontal_margin/2,
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index f4434e8..ea3c012 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -36,4 +36,15 @@
<integer name="qs_security_footer_maxLines">1</integer>
<bool name="config_use_large_screen_shade_header">true</bool>
+
+ <!-- A collection of defaults for the quick affordances on the lock screen. Each item must be a
+ string with two parts: the ID of the slot and the comma-delimited list of affordance IDs,
+ separated by a colon ':' character. For example: <item>bottom_end:home,wallet</item>. The
+ default is displayed by System UI as long as the user hasn't made a different choice for that
+ slot. If the user did make a choice, even if the choice is the "None" option, the default is
+ ignored. -->
+ <string-array name="config_keyguardQuickAffordanceDefaults" translatable="false">
+ <item>bottom_start:home</item>
+ <item>bottom_end:create_note</item>
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 9bc0dde..db7fb48 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -30,10 +30,6 @@
<!-- Margin on the left side of the carrier text on Keyguard -->
<dimen name="keyguard_carrier_text_margin">24dp</dimen>
- <!-- The width/height of the phone/camera/unlock icon on keyguard. -->
- <dimen name="keyguard_affordance_height">80dp</dimen>
- <dimen name="keyguard_affordance_width">120dp</dimen>
-
<!-- Screen pinning request width -->
<dimen name="screen_pinning_request_width">400dp</dimen>
<!-- Screen pinning request bottom button circle widths -->
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d2774ef..2276e75 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"கீழ் எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"இடது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"வலது எல்லை <xliff:g id="PERCENT">%1$d</xliff:g> சதவீதம்"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"ஸ்கிரீன் ரெக்கார்டர்"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"நடுத்தரமானது"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"சிறியது"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"பெரியது"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"மூடுக"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"மாற்று"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"சாளரத்தைப் பெரிதாக்கும் கருவிக்கான அமைப்புகள்"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"அணுகல்தன்மை அம்சத்தை திறக்க தட்டவும். அமைப்பில் பட்டனை பிரத்தியேகமாக்கலாம்/மாற்றலாம்.\n\n"<annotation id="link">"அமைப்பில் காண்க"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"பட்டனைத் தற்காலிகமாக மறைக்க ஓரத்திற்கு நகர்த்தும்"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"செயல்தவிர்"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ஷார்ட்கட் அகற்றப்பட்டது"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ஷார்ட்கட் அகற்றப்பட்டது}other{# ஷார்ட்கட்கள் அகற்றப்பட்டன}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"மேலே இடதுபுறத்திற்கு நகர்த்து"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"மேலே வலதுபுறத்திற்கு நகர்த்து"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"கீழே இடதுபுறத்திற்கு நகர்த்து"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="SONG_NAME">%1$s</xliff:g> பாடலை <xliff:g id="APP_LABEL">%2$s</xliff:g> ஆப்ஸில் பிளேசெய்"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"செயல்தவிர்"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்தில் இயக்க உங்கள் சாதனத்தை அருகில் எடுத்துச் செல்லுங்கள்"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"இங்கு பிளே செய்ய உங்கள் சாதனத்தை <xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்திற்கு அருகில் நகர்த்துங்கள்"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> சாதனத்தில் பிளே ஆகிறது"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ஏதோ தவறாகிவிட்டது. மீண்டும் முயலவும்."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"ஏற்றுகிறது"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ஒலியளவு"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ஸ்பீக்கர்கள் & டிஸ்ப்ளேக்கள்"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"பிராட்காஸ்ட் எவ்வாறு செயல்படுகிறது?"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"பிராட்காஸ்ட்"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"நீங்கள் பிராட்காஸ்ட் செய்யும் மீடியாவை அருகிலுள்ளவர்கள் இணக்கமான புளூடூத் சாதனங்கள் மூலம் கேட்கலாம்"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ இந்தத் திரை ஆஃப் ஆகிவிடும்"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"மடக்கத்தக்க சாதனம் திறக்கப்படுகிறது"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"மடக்கத்தக்க சாதனம் ஃபிளிப் செய்யப்பட்டு திருப்பப்படுகிறது"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"ஸ்டைலஸின் பேட்டரி குறைவாக உள்ளது"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 0dcf01c..a749277 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"దిగువ సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ఎడమ వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"కుడి వైపు సరిహద్దు <xliff:g id="PERCENT">%1$d</xliff:g> శాతం"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"వర్క్ స్క్రీన్షాట్లు <xliff:g id="APP">%1$s</xliff:g> యాప్లో సేవ్ చేయబడతాయి"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ఫైల్స్"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"స్క్రీన్ రికార్డర్"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"మధ్యస్థం"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"చిన్నది"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"పెద్దది"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"మూసివేయండి"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ఎడిట్ చేయండి"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"మాగ్నిఫయర్ విండో సెట్టింగ్లు"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"యాక్సెసిబిలిటీ ఫీచర్లను తెరవడానికి ట్యాప్ చేయండి. సెట్టింగ్లలో ఈ బటన్ను అనుకూలంగా మార్చండి లేదా రీప్లేస్ చేయండి.\n\n"<annotation id="link">"వీక్షణ సెట్టింగ్లు"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"తాత్కాలికంగా దానిని దాచడానికి బటన్ను చివరకు తరలించండి"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"చర్య రద్దు చేయండి"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> షార్ట్కట్ తీసివేయబడింది"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# షార్ట్కట్ తీసివేయబడింది}other{# షార్ట్కట్లు తీసివేయబడ్డాయి}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ఎగువ ఎడమ వైపునకు తరలించు"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ఎగువ కుడి వైపునకు తరలించు"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"దిగువ ఎడమ వైపునకు తరలించు"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> నుండి <xliff:g id="SONG_NAME">%1$s</xliff:g>ను ప్లే చేయండి"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"చర్య రద్దు"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>లో ప్లే చేయడానికి దగ్గరగా వెళ్లండి"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ఇక్కడ ప్లే చేయడానికి <xliff:g id="DEVICENAME">%1$s</xliff:g>కి దగ్గరగా వెళ్లండి"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g>లో ప్లే అవుతోంది"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"ఏదో తప్పు జరిగింది. మళ్లీ ట్రై చేయండి."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"లోడ్ అవుతోంది"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"టాబ్లెట్"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"వాల్యూమ్"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"స్పీకర్లు & డిస్ప్లేలు"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"సూచించబడిన పరికరాలు"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"ప్రసారం కావడం అనేది ఎలా పని చేస్తుంది"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ప్రసారం"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"మీకు సమీపంలో ఉన్న వ్యక్తులు అనుకూలత ఉన్న బ్లూటూత్ పరికరాలతో మీరు ప్రసారం చేస్తున్న మీడియాను వినగలరు"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ ఈ స్క్రీన్ ఆఫ్ అవుతుంది"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"మడవగల పరికరం విప్పబడుతోంది"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"మడవగల పరికరం చుట్టూ తిప్పబడుతోంది"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"తక్కువ స్టైలస్ బ్యాటరీ"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index e59aae2..e72471b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"ขอบเขตด้านล่าง <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"ขอบเขตด้านซ้าย <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"ขอบเขตด้านขวา <xliff:g id="PERCENT">%1$d</xliff:g> เปอร์เซ็นต์"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"ภาพหน้าจองานจะบันทึกอยู่ในแอป <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"ไฟล์"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"โปรแกรมบันทึกหน้าจอ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"ปานกลาง"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"เล็ก"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"ใหญ่"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"ปิด"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"แก้ไข"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"การตั้งค่าหน้าต่างแว่นขยาย"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"แตะเพื่อเปิดฟีเจอร์การช่วยเหลือพิเศษ ปรับแต่งหรือแทนที่ปุ่มนี้ในการตั้งค่า\n\n"<annotation id="link">"ดูการตั้งค่า"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ย้ายปุ่มไปที่ขอบเพื่อซ่อนชั่วคราว"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"เลิกทำ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"นำทางลัดฟีเจอร์<xliff:g id="FEATURE_NAME">%s</xliff:g>ออกแล้ว"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{นำทางลัด # รายการออกแล้ว}other{นำทางลัด # รายการออกแล้ว}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ย้ายไปด้านซ้ายบน"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"ย้ายไปด้านขวาบน"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"ย้ายไปด้านซ้ายล่าง"</string>
@@ -883,12 +884,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> ของ <xliff:g id="ARTIST_NAME">%2$s</xliff:g> จาก <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"เปิดเพลง <xliff:g id="SONG_NAME">%1$s</xliff:g> จาก <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"เลิกทำ"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"ขยับเข้ามาใกล้ขึ้นเพื่อเล่นใน <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"ขยับไปใกล้ <xliff:g id="DEVICENAME">%1$s</xliff:g> มากขึ้นเพื่อเล่นที่นี่"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"ขยับไปใกล้มากขึ้นเพื่อเล่นใน <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"กำลังเล่นใน <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"เกิดข้อผิดพลาด โปรดลองอีกครั้ง"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"กำลังโหลด"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"แท็บเล็ต"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"ระดับเสียง"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"ลำโพงและจอแสดงผล"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"อุปกรณ์ที่แนะนำ"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"วิธีการทำงานของการออกอากาศ"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"ประกาศ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"ผู้ที่อยู่ใกล้คุณและมีอุปกรณ์บลูทูธที่รองรับสามารถรับฟังสื่อที่คุณกำลังออกอากาศได้"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ หน้าจอนี้จะปิดไป"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"อุปกรณ์ที่พับได้กำลังกางออก"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"อุปกรณ์ที่พับได้กำลังพลิกไปมา"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"แบตเตอรี่สไตลัสเหลือน้อย"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3e59611..d8f5bad 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa ibaba"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kaliwa"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"<xliff:g id="PERCENT">%1$d</xliff:g> (na) porsyento sa hangganan sa kanan"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Naka-save ang mga screenshot sa trabaho sa <xliff:g id="APP">%1$s</xliff:g> app"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Mga File"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Recorder ng Screen"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Katamtaman"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Maliit"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Malaki"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Isara"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"I-edit"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Mga setting ng window ng magnifier"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"I-tap, buksan mga feature ng accessibility. I-customize o palitan button sa Mga Setting.\n\n"<annotation id="link">"Tingnan ang mga setting"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ilipat ang button sa gilid para pansamantala itong itago"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"I-undo"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> shortcut ang naalis"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shortcut ang naalis}one{# shortcut ang naalis}other{# na shortcut ang naalis}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Ilipat sa kaliwa sa itaas"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Ilipat sa kanan sa itaas"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Ilipat sa kaliwa sa ibaba"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"I-play ang <xliff:g id="SONG_NAME">%1$s</xliff:g> mula sa <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"I-undo"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Lumapit pa para mag-play sa <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Lumapit sa <xliff:g id="DEVICENAME">%1$s</xliff:g> para mag-play rito"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Nagpe-play sa <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Nagkaproblema. Subukan ulit."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Naglo-load"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"tablet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Hindi available ang kontrol"</string>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Volume"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Mga Speaker at Display"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Mga Iminumungkahing Device"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Paano gumagana ang pag-broadcast"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Broadcast"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Makakapakinig ang mga taong malapit sa iyo na may mga compatible na Bluetooth device sa media na bino-broadcast mo"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Mag-o-off ang screen na ito"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Ina-unfold na foldable na device"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Fini-flip na foldable na device"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Paubos na ang baterya ng stylus"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index a7b78e8..52088dbb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Alt sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Sol sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Sağ sınır yüzde <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Ekran Kaydedicisi"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Orta"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Küçük"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Büyük"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Kapat"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Düzenle"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Büyüteç penceresi ayarları"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Erişilebilirlik özelliklerini açmak için dokunun. Bu düğmeyi Ayarlar\'dan özelleştirin veya değiştirin.\n\n"<annotation id="link">"Ayarları göster"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düğmeyi geçici olarak gizlemek için kenara taşıyın"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Geri al"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> kısayol kaldırıldı"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# kısayol kaldırıldı}other{# kısayol kaldırıldı}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sol üste taşı"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Sağ üste taşı"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Sol alta taşı"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> uygulamasından <xliff:g id="ARTIST_NAME">%2$s</xliff:g>, <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> uygulamasından <xliff:g id="SONG_NAME">%1$s</xliff:g> şarkısını çal"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Geri al"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında çalmak için yaklaşın"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Burada oynatmak için <xliff:g id="DEVICENAME">%1$s</xliff:g> cihazına yaklaşın"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oynatmak için yaklaşın"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> cihazında oynatılıyor"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Bir sorun oldu. Tekrar deneyin."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Yükleme"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ses düzeyi"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Hoparlörler ve Ekranlar"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Yayınlamanın işleyiş şekli"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Anons"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Yakınınızda ve uyumlu Bluetooth cihazları olan kişiler yayınladığınız medya içeriğini dinleyebilir"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ * Bu ekran kapatılacak"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Katlanabilir cihaz açılıyor"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Katlanabilir cihaz döndürülüyor"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Ekran kaleminin pil seviyesi düşük"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d2f3001..9638c65 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Знизу на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Зліва на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Справа на <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Запис відео з екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Звичайна"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Мала"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Велика"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Закрити"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Змінити"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Налаштування розміру лупи"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Кнопка спеціальних можливостей. Змініть або замініть її в Налаштуваннях.\n\n"<annotation id="link">"Переглянути налаштування"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Щоб тимчасово сховати кнопку, перемістіть її на край екрана"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Відмінити"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Ярлик функції \"<xliff:g id="FEATURE_NAME">%s</xliff:g>\" вилучено"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ярлик вилучено}one{# ярлик вилучено}few{# ярлики вилучено}many{# ярликів вилучено}other{# ярлика вилучено}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перемістити ліворуч угору"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Перемістити праворуч угору"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Перемістити ліворуч униз"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Увімкнути пісню \"<xliff:g id="SONG_NAME">%1$s</xliff:g>\" у додатку <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Відмінити"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Щоб відтворити контент на пристрої <xliff:g id="DEVICENAME">%1$s</xliff:g>, наблизьтеся до нього"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Наблизьтеся до пристрою <xliff:g id="DEVICENAME">%1$s</xliff:g>, щоб відтворити медіафайли на ньому"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Відтворюється на пристрої <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Сталася помилка. Повторіть спробу."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Завантаження"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Не знайдено"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Гучність"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Колонки й екрани"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Як працює трансляція"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Трансляція"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Люди поблизу, які мають сумісні пристрої з Bluetooth, можуть слухати медіаконтент, який ви транслюєте."</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Цей екран вимкнеться"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Розкладний пристрій у розкладеному стані"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Розкладний пристрій обертається"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Низький заряд акумулятора стилуса"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 9db36c3..46acc98 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"نیچے کا احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"بایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"دایاں احاطہ <xliff:g id="PERCENT">%1$d</xliff:g> فیصد"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"اسکرین ریکارڈر"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"متوسط"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"چھوٹا"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"بڑا"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"بند کریں"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"ترمیم کریں"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"میگنیفائر ونڈو کی ترتیبات"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ایکسیسبیلٹی خصوصیات کھولنے کے لیے تھپتھپائیں۔ ترتیبات میں اس بٹن کو حسب ضرورت بنائیں یا تبدیل کریں۔\n\n"<annotation id="link">"ترتیبات ملاحظہ کریں"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"عارضی طور پر بٹن کو چھپانے کے لئے اسے کنارے پر لے جائیں"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"کالعدم کریں"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> شارٹ کٹ ہٹا دیا گیا"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# شارٹ کٹ ہٹا دیا گیا}other{# شارٹ کٹس ہٹا دیے گئے}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"اوپر بائیں جانب لے جائیں"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"اوپر دائیں جانب لے جائيں"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"نیچے بائیں جانب لے جائیں"</string>
@@ -883,11 +886,13 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> سے <xliff:g id="ARTIST_NAME">%2$s</xliff:g> کا <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> سے <xliff:g id="SONG_NAME">%1$s</xliff:g> چلائیں"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"کالعدم کریں"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چلانے کے لیے قریب کریں"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"یہاں چلانے کے ليے <xliff:g id="DEVICENAME">%1$s</xliff:g> کے قریب جائیں"</string>
- <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چل رہا ہے"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چلانے کے لیے قریب کریں"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
+ <string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> پر چل رہا ہے"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"کچھ غلط ہوگیا۔ پھر کوشش کریں۔"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"لوڈ ہو رہا ہے"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"والیوم"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"%%<xliff:g id="PERCENTAGE">%1$d</xliff:g>"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"اسپیکرز اور ڈسپلیز"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"براڈکاسٹنگ کیسے کام کرتا ہے"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"براڈکاسٹ"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"موافق بلوٹوتھ آلات کے ساتھ آپ کے قریبی لوگ آپ کے نشر کردہ میڈیا کو سن سکتے ہیں"</string>
@@ -1053,5 +1060,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ یہ اسکرین آف ہو جائے گی"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"فولڈ ہونے والے آلے کو کھولا جا رہا ہے"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"فولڈ ہونے والے آلے کو گھمایا جا رہا ہے"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"اسٹائلس بیٹری کم ہے"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"<xliff:g id="PERCENTAGE">%s</xliff:g> بیٹری باقی ہے"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"اپنے اسٹائلس کو چارجر منسلک کریں"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 6ab3d6c..ef7dbad 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Quyi chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Chap chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Oʻng chegara <xliff:g id="PERCENT">%1$d</xliff:g> foiz"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"Ish skrinshotlari <xliff:g id="APP">%1$s</xliff:g> ilovasida saqlanadi"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"Fayllar"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"Ekrandan yozib olish"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Oʻrtacha"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Kichik"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Yirik"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Yopish"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Tahrirlash"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Lupa oynasi sozlamalari"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Maxsus imkoniyatlarni ochish uchun bosing Sozlamalardan moslay yoki almashtira olasiz.\n\n"<annotation id="link">"Sozlamalar"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Vaqtinchalik berkitish uchun tugmani qirra tomon suring"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Bekor qilish"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ta yorliq olindi"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ta yorliq olindi}other{# ta yorliq olindi}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuqori chapga surish"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Yuqori oʻngga surish"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Quyi chapga surish"</string>
@@ -883,12 +884,12 @@
<string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> ilovasida ijro etish: <xliff:g id="SONG_NAME">%1$s</xliff:g> – <xliff:g id="ARTIST_NAME">%2$s</xliff:g>"</string>
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"<xliff:g id="APP_LABEL">%2$s</xliff:g> ilovasida ijro etilmoqda: <xliff:g id="SONG_NAME">%1$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Qaytarish"</string>
- <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g>da ijro etish uchun yaqinroq keling"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Bu yerda ijro qilish uchun <xliff:g id="DEVICENAME">%1$s</xliff:g>qurilmasiga yaqinlashtiring"</string>
+ <string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"<xliff:g id="DEVICENAME">%1$s</xliff:g> qurilmasida ijro qilish uchun unga yaqinlashing"</string>
+ <string name="media_move_closer_to_end_cast" msgid="7302555909119374738">"Shu yerda ijro qilish uchun <xliff:g id="DEVICENAME">%1$s</xliff:g>ga yaqinroq suring"</string>
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"<xliff:g id="DEVICENAME">%1$s</xliff:g> qurilmasida ijro qilinmoqda"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Xatolik yuz berdi. Qayta urining."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Yuklanmoqda"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"planshet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string>
<string name="controls_error_removed_title" msgid="1207794911208047818">"Boshqarish imkonsiz"</string>
@@ -912,6 +913,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Tovush balandligi"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Karnaylar va displeylar"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"Taklif qilingan qurilmalar"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Translatsiya qanday ishlaydi"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Translatsiya"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Atrofingizdagi mos Bluetooth qurilmasiga ega foydalanuvchilar siz translatsiya qilayotgan mediani tinglay olishadi"</string>
@@ -1053,5 +1055,6 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Bu ekran oʻchiriladi"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Buklanadigan qurilma ochilmoqda"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Buklanadigan qurilma aylantirilmoqda"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Stilus batareyasi kam"</string>
+ <string name="stylus_battery_low_percentage" msgid="1620068112350141558">"Batareya quvvati: <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+ <string name="stylus_battery_low_subtitle" msgid="3583843128908823273">"Stilusni quvvat manbaiga ulang"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 69056d5..4ba82a1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Cạnh dưới cùng <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Cạnh trái <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Cạnh phải <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Trình ghi màn hình"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Vừa"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Nhỏ"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Lớn"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Đóng"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Chỉnh sửa"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Chế độ cài đặt cửa sổ phóng to"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Nhấn để mở bộ tính năng hỗ trợ tiếp cận. Tuỳ chỉnh/thay thế nút này trong phần Cài đặt.\n\n"<annotation id="link">"Xem chế độ cài đặt"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Di chuyển nút sang cạnh để ẩn nút tạm thời"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Huỷ"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá lối tắt <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Đã xoá # lối tắt}other{Đã xoá # lối tắt}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Chuyển lên trên cùng bên trái"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Chuyển lên trên cùng bên phải"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Chuyển tới dưới cùng bên trái"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Phát <xliff:g id="SONG_NAME">%1$s</xliff:g> trên <xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Hủy"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Đưa thiết bị đến gần hơn để phát trên <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Di chuyển đến gần <xliff:g id="DEVICENAME">%1$s</xliff:g> hơn để phát tại đây"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Đang phát trên <xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Đã xảy ra lỗi. Hãy thử lại."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Đang tải"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Âm lượng"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Loa và màn hình"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Cách tính năng truyền hoạt động"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Truyền"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Những người ở gần có thiết bị Bluetooth tương thích có thể nghe nội dung nghe nhìn bạn đang truyền"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Màn hình này sẽ tắt"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Thiết bị có thể gập lại đang được mở ra"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Thiết bị có thể gập lại đang được lật ngược"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Bút cảm ứng bị yếu pin"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 48df522..4426839 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"底部边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右侧边界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"屏幕录制器"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
@@ -385,8 +389,8 @@
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"允许 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或录制吗?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"整个屏幕"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"单个应用"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"在您进行分享、录制或投射时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问您的屏幕显示或设备播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"在您进行分享、录制或投射时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问通过此应用显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"当您进行分享、录制或投屏时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问您的屏幕上显示的或设备上播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"当您对一款应用进行分享、录制或投屏时,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以访问该应用中显示或播放的所有内容。因此,请注意保护密码、付款信息、消息或其他敏感信息。"</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"继续"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或录制应用"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"是否允许此应用进行分享或录制?"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"小"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"大"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"关闭"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"修改"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"放大镜窗口设置"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"点按即可打开无障碍功能。您可在“设置”中自定义或更换此按钮。\n\n"<annotation id="link">"查看设置"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"将按钮移到边缘,即可暂时将其隐藏"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"撤消"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除快捷方式 <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 个快捷方式}other{已移除 # 个快捷方式}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移至左上角"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移至右上角"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"移至左下角"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"通过<xliff:g id="APP_LABEL">%2$s</xliff:g>播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"撤消"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"若要在“<xliff:g id="DEVICENAME">%1$s</xliff:g>”上播放,请靠近这台设备"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"若要在此设备上播放,请靠近“<xliff:g id="DEVICENAME">%1$s</xliff:g>”"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在“<xliff:g id="DEVICENAME">%1$s</xliff:g>”上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"出了点问题,请重试。"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"正在加载"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"未找到"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"音箱和显示屏"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"广播的运作方式"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"广播"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近使用兼容蓝牙设备的用户可以收听您广播的媒体内容"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此屏幕将会关闭"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展开可折叠设备"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻转可折叠设备"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"触控笔电池电量低"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index a0a3fed..04a06bc 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -91,13 +91,15 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右方邊界 <xliff:g id="PERCENT">%1$d</xliff:g>%%"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"工作的螢幕截圖會儲存在「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"螢幕畫面錄影工具"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"要開始錄製嗎?"</string>
<string name="screenrecord_description" msgid="1123231719680353736">"錄影時,Android 系統可擷取螢幕上顯示或裝置播放的任何敏感資料,包括密碼、付款資料、相片、訊息和音訊。"</string>
<string name="screenrecord_option_entire_screen" msgid="1732437834603426934">"錄製整個螢幕畫面"</string>
- <string name="screenrecord_option_single_app" msgid="5954863081500035825">"錄製單一應用程式"</string>
+ <string name="screenrecord_option_single_app" msgid="5954863081500035825">"錄製一個應用程式"</string>
<string name="screenrecord_warning_entire_screen" msgid="8141407178104195610">"進行錄製時,Android 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="screenrecord_warning_single_app" msgid="7760723997065948283">"錄製應用程式時,Android 可存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="screenrecord_start_recording" msgid="348286842544768740">"開始錄製"</string>
@@ -384,8 +386,8 @@
<string name="media_projection_dialog_title" msgid="3316063622495360646">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」開始錄影或投放嗎?"</string>
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"允許 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或錄製嗎?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"整個螢幕畫面"</string>
- <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"單一應用程式"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
+ <string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"一個應用程式"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"當您分享、錄製或投放應用程式時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取在螢幕畫面上顯示或在裝置上播放的所有內容。因此請小心保管密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他敏感資料。"</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"繼續"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或錄製應用程式"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"小"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"大"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"關閉"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"編輯"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"放大鏡視窗設定"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"㩒一下就可以開無障礙功能。喺「設定」度自訂或者取代呢個按鈕。\n\n"<annotation id="link">"查看設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣即可暫時隱藏"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"復原"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」捷徑"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個捷徑}other{已移除 # 個捷徑}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移去左上方"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移去右上方"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"移到左下方"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"在 <xliff:g id="APP_LABEL">%2$s</xliff:g> 播放《<xliff:g id="SONG_NAME">%1$s</xliff:g>》"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"復原"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"如要在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放,請靠近一點"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"如要在此裝置上播放,請靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"載入中"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"平板電腦"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"喇叭和螢幕"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播運作方式"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"附近有兼容藍牙裝置的人可收聽您正在廣播的媒體內容"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 此螢幕將關閉"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"觸控筆電量不足"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fd35f51..1df1cfb 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -91,6 +91,8 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"下方邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"左側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"右側邊界百分之 <xliff:g id="PERCENT">%1$d</xliff:g>"</string>
+ <string name="screenshot_work_profile_notification" msgid="2812417845875653929">"工作的螢幕截圖會儲存在「<xliff:g id="APP">%1$s</xliff:g>」應用程式"</string>
+ <string name="screenshot_default_files_app_name" msgid="8721579578575161912">"檔案"</string>
<string name="screenrecord_name" msgid="2596401223859996572">"螢幕錄影器"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
@@ -385,8 +387,8 @@
<string name="media_projection_permission_dialog_title" msgid="7130975432309482596">"允許 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 分享或錄製?"</string>
<string name="media_projection_permission_dialog_option_entire_screen" msgid="392086473225692983">"整個螢幕畫面"</string>
<string name="media_projection_permission_dialog_option_single_app" msgid="1591110238124910521">"單一應用程式"</string>
- <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"進行分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
- <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"進行分享、錄製或投放應用程式時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取在該應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+ <string name="media_projection_permission_dialog_warning_entire_screen" msgid="3989078820637452717">"分享、錄製或投放時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取顯示在螢幕畫面上或在裝置上播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
+ <string name="media_projection_permission_dialog_warning_single_app" msgid="1659532781536753059">"分享、錄製或投放應用程式時,<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 可以存取在應用程式中顯示或播放的所有內容。因此請謹慎處理密碼、付款資料、訊息或其他機密資訊。"</string>
<string name="media_projection_permission_dialog_continue" msgid="1827799658916736006">"繼續"</string>
<string name="media_projection_permission_app_selector_title" msgid="894251621057480704">"分享或錄製應用程式"</string>
<string name="media_projection_permission_dialog_system_service_title" msgid="6827129613741303726">"要允許這個應用程式分享或錄製嗎?"</string>
@@ -810,16 +812,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"中"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"小"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"大"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"關閉"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"編輯"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"放大鏡視窗設定"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"輕觸即可開啟無障礙功能。你可以前往「設定」自訂或更換這個按鈕。\n\n"<annotation id="link">"查看設定"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣處即可暫時隱藏"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"復原"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」捷徑"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個捷徑}other{已移除 # 個捷徑}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移到左上方"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"移到右上方"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"移到左下方"</string>
@@ -884,11 +885,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"透過「<xliff:g id="APP_LABEL">%2$s</xliff:g>」播放〈<xliff:g id="SONG_NAME">%1$s</xliff:g>〉"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"復原"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"如要在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放,請靠近一點"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"如要在這部裝置上播放,請移到更靠近「<xliff:g id="DEVICENAME">%1$s</xliff:g>」的位置"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"正在「<xliff:g id="DEVICENAME">%1$s</xliff:g>」上播放"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"發生錯誤,請再試一次。"</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
- <skip />
+ <string name="media_transfer_loading" msgid="5544017127027152422">"載入中"</string>
+ <string name="media_ttt_default_device_type" msgid="4457646436153370169">"平板電腦"</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>
@@ -912,6 +914,7 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"音量"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"喇叭和螢幕"</string>
+ <string name="media_output_group_title_suggested_device" msgid="4157186235837903826">"建議的裝置"</string>
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"廣播功能的運作方式"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"廣播"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"如果附近的人有相容的藍牙裝置,就可以聽到你正在廣播的媒體內容"</string>
@@ -1053,5 +1056,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ 這麼做會關閉這個螢幕"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"正在展開的折疊式裝置"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"正在翻轉折疊式裝置"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"觸控筆電力不足"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 3a57ace..a0153b3 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -91,6 +91,10 @@
<string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ophansi"</string>
<string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesobunxele"</string>
<string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Iphesenti elingu-<xliff:g id="PERCENT">%1$d</xliff:g> lomngcele ongakwesokudla"</string>
+ <!-- no translation found for screenshot_work_profile_notification (2812417845875653929) -->
+ <skip />
+ <!-- no translation found for screenshot_default_files_app_name (8721579578575161912) -->
+ <skip />
<string name="screenrecord_name" msgid="2596401223859996572">"Irekhoda yesikrini"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
@@ -810,16 +814,15 @@
<string name="accessibility_magnification_medium" msgid="6994632616884562625">"Kumaphakathi"</string>
<string name="accessibility_magnification_small" msgid="8144502090651099970">"Esincane"</string>
<string name="accessibility_magnification_large" msgid="6602944330021308774">"Obukhulu"</string>
- <string name="accessibility_magnification_close" msgid="1099965835844673375">"Vala"</string>
+ <!-- no translation found for accessibility_magnification_done (263349129937348512) -->
+ <skip />
<string name="accessibility_magnifier_edit" msgid="1522877239671820636">"Hlela"</string>
<string name="accessibility_magnification_magnifier_window_settings" msgid="2834685072221468434">"Amasethingi ewindi lesikhulisi"</string>
<string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Thepha ukuze uvule izakhi zokufinyelela. Enza ngendlela oyifisayo noma shintsha le nkinobho Kumasethingi.\n\n"<annotation id="link">"Buka amasethingi"</annotation></string>
<string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Hambisa inkinobho onqenqemeni ukuze uyifihle okwesikhashana"</string>
<string name="accessibility_floating_button_undo" msgid="511112888715708241">"Hlehlisa"</string>
- <!-- no translation found for accessibility_floating_button_undo_message_label_text (9017658016426242640) -->
- <skip />
- <!-- no translation found for accessibility_floating_button_undo_message_number_text (4909270290725226075) -->
- <skip />
+ <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Isinqamuleli se-<xliff:g id="FEATURE_NAME">%s</xliff:g> sisusiwe"</string>
+ <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Isinqamuleli esingu-# sisusiwe}one{Izinqamuleli ezingu-# zisusiwe}other{Izinqamuleli ezingu-# zisusiwe}}"</string>
<string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Hamba phezulu kwesokunxele"</string>
<string name="accessibility_floating_button_action_move_top_right" msgid="6106225581993479711">"Hamba phezulu ngakwesokudla"</string>
<string name="accessibility_floating_button_action_move_bottom_left" msgid="8063394111137429725">"Hamba phansi ngakwesokunxele"</string>
@@ -884,10 +887,12 @@
<string name="controls_media_smartspace_rec_item_no_artist_description" msgid="8703614798636591077">"Dlala i-<xliff:g id="SONG_NAME">%1$s</xliff:g> kusuka ku-<xliff:g id="APP_LABEL">%2$s</xliff:g>"</string>
<string name="media_transfer_undo" msgid="1895606387620728736">"Hlehlisa"</string>
<string name="media_move_closer_to_start_cast" msgid="2673104707465013176">"Sondeza eduze ukudlala ku-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
- <string name="media_move_closer_to_end_cast" msgid="6495907340926563656">"Sondela eduze ne-<xliff:g id="DEVICENAME">%1$s</xliff:g> ukuze udlale lapha"</string>
+ <!-- no translation found for media_move_closer_to_end_cast (7302555909119374738) -->
+ <skip />
<string name="media_transfer_playing_different_device" msgid="7186806382609785610">"Idlala ku-<xliff:g id="DEVICENAME">%1$s</xliff:g>"</string>
<string name="media_transfer_failed" msgid="7955354964610603723">"Kukhona okungahambanga kahle. Zama futhi."</string>
- <!-- no translation found for media_transfer_loading (5544017127027152422) -->
+ <string name="media_transfer_loading" msgid="5544017127027152422">"Iyalayisha"</string>
+ <!-- no translation found for media_ttt_default_device_type (4457646436153370169) -->
<skip />
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
<string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string>
@@ -912,6 +917,8 @@
<string name="media_output_dialog_accessibility_seekbar" msgid="5332843993805568978">"Ivolumu"</string>
<string name="media_output_dialog_volume_percentage" msgid="1613984910585111798">"<xliff:g id="PERCENTAGE">%1$d</xliff:g>%%"</string>
<string name="media_output_group_title_speakers_and_displays" msgid="7169712332365659820">"Izipikha Neziboniso"</string>
+ <!-- no translation found for media_output_group_title_suggested_device (4157186235837903826) -->
+ <skip />
<string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Indlela ukusakaza okusebenza ngayo"</string>
<string name="media_output_broadcast" msgid="3555580945878071543">"Sakaza"</string>
<string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Abantu abaseduze nawe abanamadivayisi e-Bluetooth ahambisanayo bangalalela imidiya oyisakazayo"</string>
@@ -1053,5 +1060,8 @@
<string name="rear_display_bottom_sheet_warning" msgid="800995919558238930"><b>"✱ Lesi sikrini sizovala"</b></string>
<string name="rear_display_accessibility_folded_animation" msgid="1538121649587978179">"Idivayisi egoqekayo iyembulwa"</string>
<string name="rear_display_accessibility_unfolded_animation" msgid="1946153682258289040">"Idivayisi egoqekayo iphendulwa nxazonke"</string>
- <string name="stylus_battery_low" msgid="7134370101603167096">"Ibhethri le-stylus liphansi"</string>
+ <!-- no translation found for stylus_battery_low_percentage (1620068112350141558) -->
+ <skip />
+ <!-- no translation found for stylus_battery_low_subtitle (3583843128908823273) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fc67015..6202939 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -762,12 +762,10 @@
<dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
<!-- The width/height of the keyguard bottom area icon view on keyguard. -->
- <dimen name="keyguard_affordance_height">48dp</dimen>
- <dimen name="keyguard_affordance_width">48dp</dimen>
-
<dimen name="keyguard_affordance_fixed_height">48dp</dimen>
<dimen name="keyguard_affordance_fixed_width">48dp</dimen>
<dimen name="keyguard_affordance_fixed_radius">24dp</dimen>
+
<!-- Amount the button should shake when it's not long-pressed for long enough. -->
<dimen name="keyguard_affordance_shake_amplitude">8dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4a89bb4..3d3bb6e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1511,10 +1511,10 @@
<string name="notification_conversation_summary_low">No sound or vibration and appears lower in conversation section</string>
<!-- [CHAR LIMIT=150] Notification Importance title: normal importance level summary -->
- <string name="notification_channel_summary_default">May ring or vibrate based on phone settings</string>
+ <string name="notification_channel_summary_default">May ring or vibrate based on device settings</string>
<!-- [CHAR LIMIT=150] Conversation Notification Importance title: normal conversation level, with bubbling summary -->
- <string name="notification_channel_summary_default_with_bubbles">May ring or vibrate based on phone settings. Conversations from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubble by default.</string>
+ <string name="notification_channel_summary_default_with_bubbles">May ring or vibrate based on device settings. Conversations from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubble by default.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary -->
<string name="notification_channel_summary_automatic">Have the system determine if this notification should make sound or vibration</string>
@@ -2522,6 +2522,8 @@
<string name="media_output_group_title_speakers_and_displays">Speakers & Displays</string>
<!-- Title for Suggested Devices group. [CHAR LIMIT=NONE] -->
<string name="media_output_group_title_suggested_device">Suggested Devices</string>
+ <!-- Sub status indicates device need premium account. [CHAR LIMIT=NONE] -->
+ <string name="media_output_status_require_premium">Requires premium account</string>
<!-- Media Output Broadcast Dialog -->
<!-- Title for Broadcast First Notify Dialog [CHAR LIMIT=60] -->
@@ -2896,4 +2898,25 @@
<string name="stylus_battery_low_percentage"><xliff:g id="percentage" example="16%">%s</xliff:g> battery remaining</string>
<!-- Subtitle for the notification sent when a stylus battery is low. [CHAR LIMIT=none]-->
<string name="stylus_battery_low_subtitle">Connect your stylus to a charger</string>
+
+ <!-- Title for notification of low stylus battery. [CHAR_LIMIT=NONE] -->
+ <string name="stylus_battery_low">Stylus battery low</string>
+
+ <!-- Label for a lock screen shortcut to start the camera in video mode. [CHAR_LIMIT=16] -->
+ <string name="video_camera">Video camera</string>
+
+ <!-- Switch to work profile dialer app for placing a call dialog. -->
+ <!-- Text for Switch to work profile dialog's Title. Switch to work profile dialog guide users to make call from work
+ profile dialer app as it's not possible to make call from current profile due to an admin policy. [CHAR LIMIT=60] -->
+ <string name="call_from_work_profile_title">Can\'t call from this profile</string>
+ <!-- Text for switch to work profile for call dialog to guide users to make call from work
+ profile dialer app as it's not possible to make call from current profile due to an admin policy. [CHAR LIMIT=NONE]
+ -->
+ <string name="call_from_work_profile_text">Your work policy allows you to make phone calls only from the work profile</string>
+ <!-- Label for the button to switch to work profile for placing call. Switch to work profile dialog guide users to make call from work
+ profile dialer app as it's not possible to make call from current profile due to an admin policy.[CHAR LIMIT=60] -->
+ <string name="call_from_work_profile_action">Switch to work profile</string>
+ <!-- Label for the close button on switch to work profile dialog. Switch to work profile dialog guide users to make call from work
+ profile dialer app as it's not possible to make call from current profile due to an admin policy.[CHAR LIMIT=60] -->
+ <string name="call_from_work_profile_close">Close</string>
</resources>
diff --git a/packages/SystemUI/res/xml/large_screen_shade_header.xml b/packages/SystemUI/res/xml/large_screen_shade_header.xml
index 06d425c..bf576dc 100644
--- a/packages/SystemUI/res/xml/large_screen_shade_header.xml
+++ b/packages/SystemUI/res/xml/large_screen_shade_header.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,105 +14,73 @@
~ limitations under the License.
-->
-<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
+<ConstraintSet xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/large_screen_header_constraint">
- <Constraint
- android:id="@+id/clock">
+ <Constraint android:id="@+id/clock">
<Layout
android:layout_width="wrap_content"
android:layout_height="0dp"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toStartOf="@id/date"
- app:layout_constraintHorizontal_bias="0"
- />
- <Transform
- android:scaleX="1"
- android:scaleY="1"
- />
+ app:layout_constraintStart_toEndOf="@id/begin_guide"
+ app:layout_constraintTop_toTopOf="parent" />
+ <PropertySet android:alpha="1" />
</Constraint>
- <Constraint
- android:id="@+id/date">
+ <Constraint android:id="@+id/date">
<Layout
android:layout_width="wrap_content"
android:layout_height="0dp"
+ android:layout_marginStart="8dp"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/clock"
- app:layout_constraintEnd_toStartOf="@id/carrier_group"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintHorizontal_bias="0"
- />
+ app:layout_constraintTop_toTopOf="parent" />
+ <PropertySet android:alpha="1" />
</Constraint>
- <Constraint
- android:id="@+id/carrier_group">
+ <Constraint android:id="@+id/carrier_group">
<Layout
- app:layout_constraintWidth_min="48dp"
android:layout_width="0dp"
android:layout_height="0dp"
- app:layout_constrainedWidth="true"
android:layout_gravity="end|center_vertical"
- android:layout_marginStart="8dp"
- app:layout_constraintStart_toEndOf="@id/date"
- app:layout_constraintEnd_toStartOf="@id/statusIcons"
- app:layout_constraintTop_toTopOf="@id/clock"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintHorizontal_bias="1"
- />
- <PropertySet
- android:alpha="1"
- />
+ app:layout_constraintEnd_toStartOf="@id/statusIcons"
+ app:layout_constraintStart_toEndOf="@id/date"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintWidth_default="wrap"
+ app:layout_constraintWidth_min="48dp" />
+ <PropertySet android:alpha="1" />
</Constraint>
- <Constraint
- android:id="@+id/statusIcons">
+ <Constraint android:id="@+id/statusIcons">
<Layout
- app:layout_constraintHeight_min="@dimen/large_screen_shade_header_min_height"
android:layout_width="wrap_content"
android:layout_height="@dimen/large_screen_shade_header_min_height"
- app:layout_constraintStart_toEndOf="@id/carrier_group"
- app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon"
- app:layout_constraintTop_toTopOf="@id/clock"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintHorizontal_bias="1"
- />
- <PropertySet
- android:alpha="1"
- />
+ app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/carrier_group"/>
+ <PropertySet android:alpha="1" />
</Constraint>
- <Constraint
- android:id="@+id/batteryRemainingIcon">
+ <Constraint android:id="@+id/batteryRemainingIcon">
<Layout
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintHeight_min="@dimen/large_screen_shade_header_min_height"
- app:layout_constraintStart_toEndOf="@id/statusIcons"
- app:layout_constraintEnd_toStartOf="@id/privacy_container"
- app:layout_constraintTop_toTopOf="@id/clock"
app:layout_constraintBottom_toBottomOf="parent"
- />
- <PropertySet
- android:alpha="1"
- />
+ app:layout_constraintEnd_toStartOf="@id/privacy_container"
+ app:layout_constraintTop_toTopOf="parent" />
+ <PropertySet android:alpha="1" />
</Constraint>
- <Constraint
- android:id="@+id/privacy_container">
+ <Constraint android:id="@+id/privacy_container">
<Layout
android:layout_width="wrap_content"
android:layout_height="@dimen/large_screen_shade_header_min_height"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="@id/date"
- app:layout_constraintBottom_toBottomOf="@id/date"
- app:layout_constraintStart_toEndOf="@id/batteryRemainingIcon"
- app:layout_constraintHorizontal_bias="1"
- />
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/end_guide"
+ app:layout_constraintTop_toTopOf="parent" />
</Constraint>
-
</ConstraintSet>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputDevice.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputDevice.kt
new file mode 100644
index 0000000..a9a5cf9
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputDevice.kt
@@ -0,0 +1,39 @@
+/*
+ * 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.shared.hardware
+
+import android.view.InputDevice
+
+/**
+ * Returns true if [InputDevice] is electronic components to allow a user to use an active stylus in
+ * the host device or a passive stylus is detected by the host device.
+ */
+val InputDevice.isInternalStylusSource: Boolean
+ get() = isAnyStylusSource && !isExternal
+
+/** Returns true if [InputDevice] is an active stylus. */
+val InputDevice.isExternalStylusSource: Boolean
+ get() = isAnyStylusSource && isExternal
+
+/**
+ * Returns true if [InputDevice] supports any stylus source.
+ *
+ * @see InputDevice.isInternalStylusSource
+ * @see InputDevice.isExternalStylusSource
+ */
+val InputDevice.isAnyStylusSource: Boolean
+ get() = supportsSource(InputDevice.SOURCE_STYLUS)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputManager.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputManager.kt
new file mode 100644
index 0000000..f020b4e
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/hardware/InputManager.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.shared.hardware
+
+import android.hardware.input.InputManager
+import android.view.InputDevice
+
+/**
+ * Gets information about all input devices in the system and returns as a lazy [Sequence].
+ *
+ * For performance reasons, it is preferred to operate atop the returned [Sequence] to ensure each
+ * operation is executed on an element-per-element basis yet customizable.
+ *
+ * For example:
+ * ```kotlin
+ * val stylusDevices = inputManager.getInputDeviceSequence().filter {
+ * it.supportsSource(InputDevice.SOURCE_STYLUS)
+ * }
+ *
+ * val hasInternalStylus = stylusDevices.any { it.isInternal }
+ * val hasExternalStylus = stylusDevices.any { !it.isInternal }
+ * ```
+ *
+ * @return a [Sequence] of [InputDevice].
+ */
+fun InputManager.getInputDeviceSequence(): Sequence<InputDevice> =
+ inputDeviceIds.asSequence().mapNotNull { getInputDevice(it) }
+
+/**
+ * Returns the first [InputDevice] matching the given predicate, or null if no such [InputDevice]
+ * was found.
+ */
+fun InputManager.findInputDevice(predicate: (InputDevice) -> Boolean): InputDevice? =
+ getInputDeviceSequence().find { predicate(it) }
+
+/**
+ * Returns true if [any] [InputDevice] matches with [predicate].
+ *
+ * For example:
+ * ```kotlin
+ * val hasStylusSupport = inputManager.hasInputDevice { it.isStylusSupport() }
+ * val hasStylusPen = inputManager.hasInputDevice { it.isStylusPen() }
+ * ```
+ */
+fun InputManager.hasInputDevice(predicate: (InputDevice) -> Boolean): Boolean =
+ getInputDeviceSequence().any { predicate(it) }
+
+/** Returns true if host device has any [InputDevice] where [InputDevice.isInternalStylusSource]. */
+fun InputManager.hasInternalStylusSource(): Boolean = hasInputDevice { it.isInternalStylusSource }
+
+/** Returns true if host device has any [InputDevice] where [InputDevice.isExternalStylusSource]. */
+fun InputManager.hasExternalStylusSource(): Boolean = hasInputDevice { it.isExternalStylusSource }
+
+/** Returns true if host device has any [InputDevice] where [InputDevice.isAnyStylusSource]. */
+fun InputManager.hasAnyStylusSource(): Boolean = hasInputDevice { it.isAnyStylusSource }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 1c532fe..b8bddd1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -22,6 +22,7 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.view.MotionEvent;
+import com.android.internal.util.ScreenshotRequest;
import com.android.systemui.shared.recents.model.Task;
@@ -87,12 +88,6 @@
void notifyPrioritizedRotation(int rotation) = 25;
/**
- * Handle the provided image as if it was a screenshot.
- */
- void handleImageBundleAsScreenshot(in Bundle screenImageBundle, in Rect locationInScreen,
- in Insets visibleInsets, in Task.TaskKey task) = 28;
-
- /**
* Notifies to expand notification panel.
*/
void expandNotificationPanel() = 29;
@@ -125,5 +120,10 @@
*/
void toggleNotificationPanel() = 50;
- // Next id = 51
+ /**
+ * Handle the screenshot request.
+ */
+ void takeScreenshot(in ScreenshotRequest request) = 51;
+
+ // Next id = 52
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 08567a7..6d9c5df 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -199,7 +199,7 @@
}
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
+ Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
false, /* notifyForDescendants */
mDoubleLineClockObserver,
UserHandle.USER_ALL
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt
new file mode 100644
index 0000000..249b3fe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.keyguard.logging
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.TrustModel
+import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import javax.inject.Inject
+
+/** Logging helper for trust repository. */
+@SysUISingleton
+class TrustRepositoryLogger
+@Inject
+constructor(
+ @KeyguardUpdateMonitorLog private val logBuffer: LogBuffer,
+) {
+ fun onTrustChanged(
+ enabled: Boolean,
+ newlyUnlocked: Boolean,
+ userId: Int,
+ flags: Int,
+ trustGrantedMessages: List<String>?
+ ) {
+ logBuffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ bool1 = enabled
+ bool2 = newlyUnlocked
+ int1 = userId
+ int2 = flags
+ str1 = trustGrantedMessages?.joinToString()
+ },
+ {
+ "onTrustChanged enabled: $bool1, newlyUnlocked: $bool2, " +
+ "userId: $int1, flags: $int2, grantMessages: $str1"
+ }
+ )
+ }
+
+ fun trustListenerRegistered() {
+ logBuffer.log(TAG, LogLevel.VERBOSE, "TrustRepository#registerTrustListener")
+ }
+
+ fun trustListenerUnregistered() {
+ logBuffer.log(TAG, LogLevel.VERBOSE, "TrustRepository#unregisterTrustListener")
+ }
+
+ fun trustModelEmitted(value: TrustModel) {
+ logBuffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ {
+ int1 = value.userId
+ bool1 = value.isTrusted
+ },
+ { "trustModel emitted: userId: $int1 isTrusted: $bool1" }
+ )
+ }
+
+ fun isCurrentUserTrusted(isCurrentUserTrusted: Boolean) {
+ logBuffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { bool1 = isCurrentUserTrusted },
+ { "isCurrentUserTrusted emitted: $bool1" }
+ )
+ }
+
+ companion object {
+ const val TAG = "TrustRepositoryLog"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
index fbb909f..2c97d62 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonModeObserver.java
@@ -27,6 +27,7 @@
import android.util.Log;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.settings.UserTracker;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -67,8 +68,8 @@
}
@Inject
- public AccessibilityButtonModeObserver(Context context) {
- super(context, Settings.Secure.ACCESSIBILITY_BUTTON_MODE);
+ public AccessibilityButtonModeObserver(Context context, UserTracker userTracker) {
+ super(context, userTracker, Settings.Secure.ACCESSIBILITY_BUTTON_MODE);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
index b32ebcc..53a21b3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserver.java
@@ -23,6 +23,7 @@
import androidx.annotation.Nullable;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.settings.UserTracker;
import javax.inject.Inject;
@@ -48,8 +49,8 @@
}
@Inject
- public AccessibilityButtonTargetsObserver(Context context) {
- super(context, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+ public AccessibilityButtonTargetsObserver(Context context, UserTracker userTracker) {
+ super(context, userTracker, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
index e4e0da6..326773f 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
@@ -27,6 +27,7 @@
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.settings.UserTracker;
import java.util.ArrayList;
import java.util.List;
@@ -44,6 +45,7 @@
public abstract class SecureSettingsContentObserver<T> {
private final ContentResolver mContentResolver;
+ private final UserTracker mUserTracker;
@VisibleForTesting
final ContentObserver mContentObserver;
@@ -52,9 +54,11 @@
@VisibleForTesting
final List<T> mListeners = new ArrayList<>();
- protected SecureSettingsContentObserver(Context context, String secureSettingsKey) {
+ protected SecureSettingsContentObserver(Context context, UserTracker userTracker,
+ String secureSettingsKey) {
mKey = secureSettingsKey;
mContentResolver = context.getContentResolver();
+ mUserTracker = userTracker;
mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
@@ -103,7 +107,7 @@
* See {@link Settings.Secure}.
*/
public final String getSettingsValue() {
- return Settings.Secure.getStringForUser(mContentResolver, mKey, UserHandle.USER_CURRENT);
+ return Settings.Secure.getStringForUser(mContentResolver, mKey, mUserTracker.getUserId());
}
private void updateValueChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 50449b0..c5d4bbe 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -35,14 +35,12 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
-import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
@@ -52,6 +50,7 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.recents.Recents;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -179,6 +178,7 @@
private final SystemActionsBroadcastReceiver mReceiver;
private final Context mContext;
+ private final UserTracker mUserTracker;
private final Optional<Recents> mRecentsOptional;
private Locale mLocale;
private final AccessibilityManager mA11yManager;
@@ -190,11 +190,13 @@
@Inject
public SystemActions(Context context,
+ UserTracker userTracker,
NotificationShadeWindowController notificationShadeController,
ShadeController shadeController,
Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
Optional<Recents> recentsOptional) {
mContext = context;
+ mUserTracker = userTracker;
mShadeController = shadeController;
mRecentsOptional = recentsOptional;
mReceiver = new SystemActionsBroadcastReceiver();
@@ -343,6 +345,7 @@
/**
* Register a system action.
+ *
* @param actionId the action ID to register.
*/
public void register(int actionId) {
@@ -440,6 +443,7 @@
/**
* Unregister a system action.
+ *
* @param actionId the action ID to unregister.
*/
public void unregister(int actionId) {
@@ -475,7 +479,8 @@
}
private void handleNotifications() {
- mCentralSurfacesOptionalLazy.get().ifPresent(CentralSurfaces::animateExpandNotificationsPanel);
+ mCentralSurfacesOptionalLazy.get().ifPresent(
+ CentralSurfaces::animateExpandNotificationsPanel);
}
private void handleQuickSettings() {
@@ -507,7 +512,7 @@
private void handleTakeScreenshot() {
ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
- screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+ screenshotHelper.takeScreenshot(
SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
@@ -525,7 +530,7 @@
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
final String chooserClassName = AccessibilityButtonChooserActivity.class.getName();
intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ mContext.startActivityAsUser(intent, mUserTracker.getUserHandle());
}
private void handleAccessibilityShortcut() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 9537ce0..348c2ee 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -41,6 +41,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
@@ -74,15 +75,18 @@
private final Handler mHandler;
private final WindowMagnifierCallback mWindowMagnifierCallback;
private final SysUiState mSysUiState;
+ private final SecureSettings mSecureSettings;
ControllerSupplier(Context context, Handler handler,
WindowMagnifierCallback windowMagnifierCallback,
- DisplayManager displayManager, SysUiState sysUiState) {
+ DisplayManager displayManager, SysUiState sysUiState,
+ SecureSettings secureSettings) {
super(displayManager);
mContext = context;
mHandler = handler;
mWindowMagnifierCallback = windowMagnifierCallback;
mSysUiState = sysUiState;
+ mSecureSettings = secureSettings;
}
@Override
@@ -99,7 +103,8 @@
new SurfaceControl.Transaction(),
mWindowMagnifierCallback,
mSysUiState,
- WindowManagerGlobal::getWindowSession);
+ WindowManagerGlobal::getWindowSession,
+ mSecureSettings);
}
}
@@ -109,7 +114,8 @@
@Inject
public WindowMagnification(Context context, @Main Handler mainHandler,
CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
- SysUiState sysUiState, OverviewProxyService overviewProxyService) {
+ SysUiState sysUiState, OverviewProxyService overviewProxyService,
+ SecureSettings secureSettings) {
mContext = context;
mHandler = mainHandler;
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
@@ -118,7 +124,8 @@
mSysUiState = sysUiState;
mOverviewProxyService = overviewProxyService;
mMagnificationControllerSupplier = new ControllerSupplier(context,
- mHandler, this, context.getSystemService(DisplayManager.class), sysUiState);
+ mHandler, this, context.getSystemService(DisplayManager.class), sysUiState,
+ secureSettings);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index a3dbaad..74f5f13 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -76,6 +76,7 @@
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.text.NumberFormat;
@@ -230,7 +231,8 @@
SurfaceControl.Transaction transaction,
@NonNull WindowMagnifierCallback callback,
SysUiState sysUiState,
- @NonNull Supplier<IWindowSession> globalWindowSessionSupplier) {
+ @NonNull Supplier<IWindowSession> globalWindowSessionSupplier,
+ SecureSettings secureSettings) {
mContext = context;
mHandler = handler;
mAnimationController = animationController;
@@ -249,7 +251,7 @@
mWindowBounds = new Rect(mWm.getCurrentWindowMetrics().getBounds());
mResources = mContext.getResources();
- mScale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ mScale = secureSettings.getFloatForUser(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
mResources.getInteger(R.integer.magnification_default_scale),
UserHandle.USER_CURRENT);
@@ -274,7 +276,7 @@
mWindowMagnificationSettings =
new WindowMagnificationSettings(mContext, mWindowMagnificationSettingsCallback,
- mSfVsyncFrameProvider);
+ mSfVsyncFrameProvider, secureSettings);
// Initialize listeners.
mMirrorViewRunnable = () -> {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 56602ad..527c124 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -53,6 +53,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
+import com.android.systemui.util.settings.SecureSettings;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -66,6 +67,7 @@
private final Context mContext;
private final AccessibilityManager mAccessibilityManager;
private final WindowManager mWindowManager;
+ private final SecureSettings mSecureSettings;
private final Runnable mWindowInsetChangeRunnable;
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
@@ -110,14 +112,15 @@
@VisibleForTesting
WindowMagnificationSettings(Context context, WindowMagnificationSettingsCallback callback,
- SfVsyncFrameCallbackProvider sfVsyncFrameProvider) {
+ SfVsyncFrameCallbackProvider sfVsyncFrameProvider, SecureSettings secureSettings) {
mContext = context;
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mWindowManager = mContext.getSystemService(WindowManager.class);
mSfVsyncFrameProvider = sfVsyncFrameProvider;
mCallback = callback;
+ mSecureSettings = secureSettings;
- mAllowDiagonalScrolling = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ mAllowDiagonalScrolling = mSecureSettings.getIntForUser(
Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0,
UserHandle.USER_CURRENT) == 1;
@@ -133,7 +136,7 @@
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float scale = progress * A11Y_CHANGE_SCALE_DIFFERENCE + A11Y_SCALE_MIN_VALUE;
- Settings.Secure.putFloatForUser(mContext.getContentResolver(),
+ mSecureSettings.putFloatForUser(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
UserHandle.USER_CURRENT);
mCallback.onMagnifierScale(scale);
@@ -388,7 +391,7 @@
mZoomSeekbar = mSettingView.findViewById(R.id.magnifier_zoom_seekbar);
mZoomSeekbar.setOnSeekBarChangeListener(new ZoomSeekbarChangeListener());
- float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ float scale = mSecureSettings.getFloatForUser(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 0,
UserHandle.USER_CURRENT);
setSeekbarProgress(scale);
@@ -510,11 +513,11 @@
}
private void toggleDiagonalScrolling() {
- boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ boolean enabled = mSecureSettings.getIntForUser(
Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, 0,
UserHandle.USER_CURRENT) == 1;
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ mSecureSettings.putIntForUser(
Settings.Secure.ACCESSIBILITY_ALLOW_DIAGONAL_SCROLLING, enabled ? 0 : 1,
UserHandle.USER_CURRENT);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
index de351ec..81d7766 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java
@@ -43,6 +43,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Prefs;
import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.List;
@@ -60,6 +61,7 @@
private static final float DEFAULT_POSITION_Y_PERCENT = 0.77f;
private final Context mContext;
+ private final SecureSettings mSecureSettings;
private final AccessibilityFloatingMenuView mMenuView;
private final MigrationTooltipView mMigrationTooltipView;
private final DockTooltipView mDockTooltipView;
@@ -77,7 +79,7 @@
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- mMenuView.setSizeType(getSizeType(mContext));
+ mMenuView.setSizeType(getSizeType());
}
};
@@ -85,8 +87,8 @@
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- mMenuView.updateOpacityWith(isFadeEffectEnabled(mContext),
- getOpacityValue(mContext));
+ mMenuView.updateOpacityWith(isFadeEffectEnabled(),
+ getOpacityValue());
}
};
@@ -98,16 +100,19 @@
}
};
- public AccessibilityFloatingMenu(Context context) {
+ public AccessibilityFloatingMenu(Context context, SecureSettings secureSettings) {
mContext = context;
+ mSecureSettings = secureSettings;
mMenuView = new AccessibilityFloatingMenuView(context, getPosition(context));
mMigrationTooltipView = new MigrationTooltipView(mContext, mMenuView);
mDockTooltipView = new DockTooltipView(mContext, mMenuView);
}
@VisibleForTesting
- AccessibilityFloatingMenu(Context context, AccessibilityFloatingMenuView menuView) {
+ AccessibilityFloatingMenu(Context context, SecureSettings secureSettings,
+ AccessibilityFloatingMenuView menuView) {
mContext = context;
+ mSecureSettings = secureSettings;
mMenuView = menuView;
mMigrationTooltipView = new MigrationTooltipView(mContext, mMenuView);
mDockTooltipView = new DockTooltipView(mContext, mMenuView);
@@ -130,10 +135,10 @@
mMenuView.show();
mMenuView.onTargetsChanged(targetList);
- mMenuView.updateOpacityWith(isFadeEffectEnabled(mContext),
- getOpacityValue(mContext));
- mMenuView.setSizeType(getSizeType(mContext));
- mMenuView.setShapeType(getShapeType(mContext));
+ mMenuView.updateOpacityWith(isFadeEffectEnabled(),
+ getOpacityValue());
+ mMenuView.setSizeType(getSizeType());
+ mMenuView.setShapeType(getShapeType());
mMenuView.setOnDragEndListener(this::onDragEnd);
showMigrationTooltipIfNecessary();
@@ -170,17 +175,17 @@
// Migration tooltip was the android S feature. It's just used on the Android version from R
// to S. In addition, it only shows once.
private void showMigrationTooltipIfNecessary() {
- if (isMigrationTooltipPromptEnabled(mContext)) {
+ if (isMigrationTooltipPromptEnabled()) {
mMigrationTooltipView.show();
- Settings.Secure.putInt(mContext.getContentResolver(),
+ mSecureSettings.putInt(
ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT, /* disabled */ 0);
}
}
- private static boolean isMigrationTooltipPromptEnabled(Context context) {
- return Settings.Secure.getInt(
- context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
+ private boolean isMigrationTooltipPromptEnabled() {
+ return mSecureSettings.getInt(
+ ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
DEFAULT_MIGRATION_TOOLTIP_PROMPT_IS_DISABLED) == /* enabled */ 1;
}
@@ -212,57 +217,61 @@
}
}
- private static boolean isFadeEffectEnabled(Context context) {
- return Settings.Secure.getInt(
- context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
+ private boolean isFadeEffectEnabled() {
+ return mSecureSettings.getInt(
+ ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
DEFAULT_FADE_EFFECT_IS_ENABLED) == /* enabled */ 1;
}
- private static float getOpacityValue(Context context) {
- return Settings.Secure.getFloat(
- context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_OPACITY,
+ private float getOpacityValue() {
+ return mSecureSettings.getFloat(
+ ACCESSIBILITY_FLOATING_MENU_OPACITY,
DEFAULT_OPACITY_VALUE);
}
- private static int getSizeType(Context context) {
- return Settings.Secure.getInt(
- context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_SIZE, SizeType.SMALL);
+ private int getSizeType() {
+ return mSecureSettings.getInt(
+ ACCESSIBILITY_FLOATING_MENU_SIZE, SizeType.SMALL);
}
- private static int getShapeType(Context context) {
- return Settings.Secure.getInt(
- context.getContentResolver(), ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
+ private int getShapeType() {
+ return mSecureSettings.getInt(
+ ACCESSIBILITY_FLOATING_MENU_ICON_TYPE,
ShapeType.OVAL);
}
private void registerContentObservers() {
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
/* notifyForDescendants */ false, mContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ /* notifyForDescendants */ false, mContentObserver,
+ UserHandle.USER_CURRENT);
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
/* notifyForDescendants */ false, mSizeContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED),
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
/* notifyForDescendants */ false, mFadeOutContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY),
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY,
/* notifyForDescendants */ false, mFadeOutContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES),
+ mSecureSettings.registerContentObserverForUser(
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
/* notifyForDescendants */ false,
mEnabledA11yServicesContentObserver, UserHandle.USER_CURRENT);
}
private void unregisterContentObservers() {
- mContext.getContentResolver().unregisterContentObserver(mContentObserver);
- mContext.getContentResolver().unregisterContentObserver(mSizeContentObserver);
- mContext.getContentResolver().unregisterContentObserver(mFadeOutContentObserver);
- mContext.getContentResolver().unregisterContentObserver(
+ mSecureSettings.unregisterContentObserver(mContentObserver);
+ mSecureSettings.unregisterContentObserver(mSizeContentObserver);
+ mSecureSettings.unregisterContentObserver(mFadeOutContentObserver);
+ mSecureSettings.unregisterContentObserver(
mEnabledA11yServicesContentObserver);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index 6d54d38..7fedf16 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -40,6 +40,7 @@
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -59,6 +60,7 @@
private final DisplayManager mDisplayManager;
private final AccessibilityManager mAccessibilityManager;
private final FeatureFlags mFeatureFlags;
+ private final SecureSettings mSecureSettings;
@VisibleForTesting
IAccessibilityFloatingMenu mFloatingMenu;
private int mBtnMode;
@@ -102,7 +104,8 @@
AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
AccessibilityButtonModeObserver accessibilityButtonModeObserver,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ SecureSettings secureSettings) {
mContext = context;
mWindowManager = windowManager;
mDisplayManager = displayManager;
@@ -111,6 +114,7 @@
mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mFeatureFlags = featureFlags;
+ mSecureSettings = secureSettings;
mIsKeyguardVisible = false;
}
@@ -185,9 +189,9 @@
final Context windowContext = mContext.createWindowContext(defaultDisplay,
TYPE_NAVIGATION_BAR_PANEL, /* options= */ null);
mFloatingMenu = new MenuViewLayerController(windowContext, mWindowManager,
- mAccessibilityManager);
+ mAccessibilityManager, mSecureSettings);
} else {
- mFloatingMenu = new AccessibilityFloatingMenu(mContext);
+ mFloatingMenu = new AccessibilityFloatingMenu(mContext, mSecureSettings);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
index f79c3d2..aad708a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepository.java
@@ -49,6 +49,7 @@
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Prefs;
+import com.android.systemui.util.settings.SecureSettings;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -77,6 +78,7 @@
mA11yServicesStateChangeListener = manager -> onTargetFeaturesChanged();
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final OnSettingsContentsChanged mSettingsContentsCallback;
+ private final SecureSettings mSecureSettings;
private Position mPercentagePosition;
@IntDef({
@@ -104,7 +106,7 @@
@Override
public void onChange(boolean selfChange) {
mSettingsContentsCallback.onSizeTypeChanged(
- getMenuSizeTypeFromSettings(mContext));
+ getMenuSizeTypeFromSettings());
}
};
@@ -142,11 +144,12 @@
};
MenuInfoRepository(Context context, AccessibilityManager accessibilityManager,
- OnSettingsContentsChanged settingsContentsChanged) {
+ OnSettingsContentsChanged settingsContentsChanged, SecureSettings secureSettings) {
mContext = context;
mAccessibilityManager = accessibilityManager;
mConfiguration = new Configuration(context.getResources().getConfiguration());
mSettingsContentsCallback = settingsContentsChanged;
+ mSecureSettings = secureSettings;
mPercentagePosition = getStartPosition();
}
@@ -164,7 +167,7 @@
}
void loadMigrationTooltipVisibility(OnInfoReady<Boolean> callback) {
- callback.onReady(Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ callback.onReady(mSecureSettings.getIntForUser(
ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
DEFAULT_MIGRATION_TOOLTIP_VALUE_PROMPT, UserHandle.USER_CURRENT)
== MigrationPrompt.ENABLED);
@@ -179,7 +182,7 @@
}
void loadMenuSizeType(OnInfoReady<Integer> callback) {
- callback.onReady(getMenuSizeTypeFromSettings(mContext));
+ callback.onReady(getMenuSizeTypeFromSettings());
}
void loadMenuFadeEffectInfo(OnInfoReady<MenuFadeEffectInfo> callback) {
@@ -187,8 +190,8 @@
}
private MenuFadeEffectInfo getMenuFadeEffectInfo() {
- return new MenuFadeEffectInfo(isMenuFadeEffectEnabledFromSettings(mContext),
- getMenuOpacityFromSettings(mContext));
+ return new MenuFadeEffectInfo(isMenuFadeEffectEnabledFromSettings(),
+ getMenuOpacityFromSettings());
}
void updateMoveToTucked(boolean isMoveToTucked) {
@@ -208,7 +211,7 @@
}
void updateMigrationTooltipVisibility(boolean visible) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ mSecureSettings.putIntForUser(
ACCESSIBILITY_FLOATING_MENU_MIGRATION_TOOLTIP_PROMPT,
visible ? MigrationPrompt.ENABLED : MigrationPrompt.DISABLED,
UserHandle.USER_CURRENT);
@@ -229,24 +232,25 @@
}
void registerObserversAndCallbacks() {
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS),
/* notifyForDescendants */ false, mMenuTargetFeaturesContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(ENABLED_ACCESSIBILITY_SERVICES),
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(ENABLED_ACCESSIBILITY_SERVICES),
/* notifyForDescendants */ false,
- mMenuTargetFeaturesContentObserver, UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
+ mMenuTargetFeaturesContentObserver,
+ UserHandle.USER_CURRENT);
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE),
/* notifyForDescendants */ false, mMenuSizeContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED),
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED),
/* notifyForDescendants */ false, mMenuFadeOutContentObserver,
UserHandle.USER_CURRENT);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(ACCESSIBILITY_FLOATING_MENU_OPACITY),
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(ACCESSIBILITY_FLOATING_MENU_OPACITY),
/* notifyForDescendants */ false, mMenuFadeOutContentObserver,
UserHandle.USER_CURRENT);
mContext.registerComponentCallbacks(mComponentCallbacks);
@@ -277,19 +281,19 @@
void onReady(T info);
}
- private static int getMenuSizeTypeFromSettings(Context context) {
- return Settings.Secure.getIntForUser(context.getContentResolver(),
+ private int getMenuSizeTypeFromSettings() {
+ return mSecureSettings.getIntForUser(
ACCESSIBILITY_FLOATING_MENU_SIZE, SMALL, UserHandle.USER_CURRENT);
}
- private static boolean isMenuFadeEffectEnabledFromSettings(Context context) {
- return Settings.Secure.getIntForUser(context.getContentResolver(),
+ private boolean isMenuFadeEffectEnabledFromSettings() {
+ return mSecureSettings.getIntForUser(
ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED,
DEFAULT_FADE_EFFECT_IS_ENABLED, UserHandle.USER_CURRENT) == /* enabled */ 1;
}
- private static float getMenuOpacityFromSettings(Context context) {
- return Settings.Secure.getFloatForUser(context.getContentResolver(),
+ private float getMenuOpacityFromSettings() {
+ return mSecureSettings.getFloatForUser(
ACCESSIBILITY_FLOATING_MENU_OPACITY, DEFAULT_OPACITY_VALUE,
UserHandle.USER_CURRENT);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
index 15a8d09..d0c426d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java
@@ -58,6 +58,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.systemui.R;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.bubbles.DismissView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -87,6 +88,7 @@
private final AccessibilityManager mAccessibilityManager;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final IAccessibilityFloatingMenu mFloatingMenu;
+ private final SecureSettings mSecureSettings;
private final DismissAnimationController mDismissAnimationController;
private final MenuViewModel mMenuViewModel;
private final Observer<Boolean> mDockTooltipObserver =
@@ -126,7 +128,7 @@
final Runnable mDismissMenuAction = new Runnable() {
@Override
public void run() {
- Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ mSecureSettings.putStringForUser(
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
UserHandle.USER_CURRENT);
@@ -147,7 +149,8 @@
};
MenuViewLayer(@NonNull Context context, WindowManager windowManager,
- AccessibilityManager accessibilityManager, IAccessibilityFloatingMenu floatingMenu) {
+ AccessibilityManager accessibilityManager, IAccessibilityFloatingMenu floatingMenu,
+ SecureSettings secureSettings) {
super(context);
// Simplifies the translation positioning and animations
@@ -156,8 +159,9 @@
mWindowManager = windowManager;
mAccessibilityManager = accessibilityManager;
mFloatingMenu = floatingMenu;
+ mSecureSettings = secureSettings;
- mMenuViewModel = new MenuViewModel(context, accessibilityManager);
+ mMenuViewModel = new MenuViewModel(context, accessibilityManager, secureSettings);
mMenuViewAppearance = new MenuViewAppearance(context, windowManager);
mMenuView = new MenuView(context, mMenuViewModel, mMenuViewAppearance);
mMenuAnimationController = mMenuView.getMenuAnimationController();
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
index c7be907..c52ecc5 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerController.java
@@ -24,6 +24,8 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
+import com.android.systemui.util.settings.SecureSettings;
+
/**
* Controls the {@link MenuViewLayer} whether to be attached to the window via the interface
* of {@link IAccessibilityFloatingMenu}.
@@ -34,9 +36,10 @@
private boolean mIsShowing;
MenuViewLayerController(Context context, WindowManager windowManager,
- AccessibilityManager accessibilityManager) {
+ AccessibilityManager accessibilityManager, SecureSettings secureSettings) {
mWindowManager = windowManager;
- mMenuViewLayer = new MenuViewLayer(context, windowManager, accessibilityManager, this);
+ mMenuViewLayer = new MenuViewLayer(context, windowManager, accessibilityManager, this,
+ secureSettings);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java
index eec8467..f924784 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewModel.java
@@ -23,6 +23,7 @@
import androidx.lifecycle.MutableLiveData;
import com.android.internal.accessibility.dialog.AccessibilityTarget;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.List;
@@ -42,9 +43,10 @@
private final MutableLiveData<Position> mPercentagePositionData = new MutableLiveData<>();
private final MenuInfoRepository mInfoRepository;
- MenuViewModel(Context context, AccessibilityManager accessibilityManager) {
+ MenuViewModel(Context context, AccessibilityManager accessibilityManager,
+ SecureSettings secureSettings) {
mInfoRepository = new MenuInfoRepository(context,
- accessibilityManager, /* settingsContentsChanged= */ this);
+ accessibilityManager, /* settingsContentsChanged= */ this, secureSettings);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 57ffdab..86f0d06 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -35,8 +35,10 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -119,6 +121,8 @@
private final UiController mUiController;
protected final Lazy<SysUiState> mSysUiState;
protected final AssistLogger mAssistLogger;
+ private final UserTracker mUserTracker;
+ private final SecureSettings mSecureSettings;
private final DeviceProvisionedController mDeviceProvisionedController;
private final CommandQueue mCommandQueue;
@@ -135,7 +139,9 @@
Lazy<SysUiState> sysUiState,
DefaultUiController defaultUiController,
AssistLogger assistLogger,
- @Main Handler uiHandler) {
+ @Main Handler uiHandler,
+ UserTracker userTracker,
+ SecureSettings secureSettings) {
mContext = context;
mDeviceProvisionedController = controller;
mCommandQueue = commandQueue;
@@ -143,6 +149,8 @@
mAssistDisclosure = new AssistDisclosure(context, uiHandler);
mPhoneStateMonitor = phoneStateMonitor;
mAssistLogger = assistLogger;
+ mUserTracker = userTracker;
+ mSecureSettings = secureSettings;
registerVoiceInteractionSessionListener();
@@ -273,7 +281,7 @@
CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
false /* force */);
- boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ boolean structureEnabled = mSecureSettings.getIntForUser(
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
final SearchManager searchManager =
@@ -300,7 +308,7 @@
@Override
public void run() {
mContext.startActivityAsUser(intent, opts.toBundle(),
- new UserHandle(UserHandle.USER_CURRENT));
+ mUserTracker.getUserHandle());
}
});
} catch (ActivityNotFoundException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
index e4c197f..1404053 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
@@ -35,13 +35,13 @@
override val actsAsConfirmButton: Boolean = true
- override fun shouldAnimateForTransition(
+ override fun shouldAnimateIconViewForTransition(
@BiometricState oldState: Int,
@BiometricState newState: Int
): Boolean = when (newState) {
STATE_PENDING_CONFIRMATION -> true
STATE_AUTHENTICATED -> false
- else -> super.shouldAnimateForTransition(oldState, newState)
+ else -> super.shouldAnimateIconViewForTransition(oldState, newState)
}
@RawRes
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index b962cc4..436f9df 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -104,12 +104,14 @@
iconView.frame = 0
iconViewOverlay.frame = 0
- if (shouldAnimateForTransition(lastState, newState)) {
- iconView.playAnimation()
- iconViewOverlay.playAnimation()
- } else if (lastState == STATE_IDLE && newState == STATE_AUTHENTICATING_ANIMATING_IN) {
+ if (shouldAnimateIconViewForTransition(lastState, newState)) {
iconView.playAnimation()
}
+
+ if (shouldAnimateIconViewOverlayForTransition(lastState, newState)) {
+ iconViewOverlay.playAnimation()
+ }
+
LottieColorUtils.applyDynamicColors(context, iconView)
LottieColorUtils.applyDynamicColors(context, iconViewOverlay)
}
@@ -127,7 +129,7 @@
}
iconView.frame = 0
- if (shouldAnimateForTransition(lastState, newState)) {
+ if (shouldAnimateIconViewForTransition(lastState, newState)) {
iconView.playAnimation()
}
LottieColorUtils.applyDynamicColors(context, iconView)
@@ -160,7 +162,20 @@
return if (id != null) context.getString(id) else null
}
- protected open fun shouldAnimateForTransition(
+ protected open fun shouldAnimateIconViewForTransition(
+ @BiometricState oldState: Int,
+ @BiometricState newState: Int
+ ) = when (newState) {
+ STATE_HELP,
+ STATE_ERROR -> true
+ STATE_AUTHENTICATING_ANIMATING_IN,
+ STATE_AUTHENTICATING ->
+ oldState == STATE_ERROR || oldState == STATE_HELP || oldState == STATE_IDLE
+ STATE_AUTHENTICATED -> true
+ else -> false
+ }
+
+ protected open fun shouldAnimateIconViewOverlayForTransition(
@BiometricState oldState: Int,
@BiometricState newState: Int
) = when (newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 1afa9b2..6f594d5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -111,7 +111,7 @@
context.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong()
private val isReverseDefaultRotation =
- context.getResources().getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)
+ context.resources.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)
private var overlayHideAnimator: ViewPropertyAnimator? = null
@@ -268,10 +268,12 @@
val isDefaultOrientation =
if (isReverseDefaultRotation) !isNaturalOrientation else isNaturalOrientation
val size = windowManager.maximumWindowMetrics.bounds
+
val displayWidth = if (isDefaultOrientation) size.width() else size.height()
val displayHeight = if (isDefaultOrientation) size.height() else size.width()
val boundsWidth = if (isDefaultOrientation) bounds.width() else bounds.height()
val boundsHeight = if (isDefaultOrientation) bounds.height() else bounds.width()
+
val sensorBounds =
if (overlayOffsets.isYAligned()) {
Rect(
@@ -297,6 +299,7 @@
overlayViewParams.x = sensorBounds.left
overlayViewParams.y = sensorBounds.top
+
windowManager.updateViewLayout(overlayView, overlayViewParams)
}
@@ -306,7 +309,12 @@
}
// hide after a few seconds if the sensor is oriented down and there are
// large overlapping system bars
- val rotation = context.display?.rotation
+ var rotation = context.display?.rotation
+
+ if (rotation != null) {
+ rotation = getRotationFromDefault(rotation)
+ }
+
if (
windowManager.currentWindowMetrics.windowInsets.hasBigNavigationBar() &&
((rotation == Surface.ROTATION_270 && overlayOffsets.isYAligned()) ||
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 79c09fd..7217f99 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -97,6 +97,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
@@ -166,6 +167,7 @@
@Nullable private final TouchProcessor mTouchProcessor;
@NonNull private final SessionTracker mSessionTracker;
@NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
+ @NonNull private final SecureSettings mSecureSettings;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@@ -261,7 +263,7 @@
mLockscreenShadeTransitionController, mConfigurationController,
mKeyguardStateController,
mUnlockedScreenOffAnimationController,
- mUdfpsDisplayMode, requestId, reason, callback,
+ mUdfpsDisplayMode, mSecureSettings, requestId, reason, callback,
(view, event, fromUdfpsView) -> onTouch(requestId, event,
fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags,
mPrimaryBouncerInteractor, mAlternateBouncerInteractor)));
@@ -834,7 +836,8 @@
@NonNull PrimaryBouncerInteractor primaryBouncerInteractor,
@NonNull SinglePointerTouchProcessor singlePointerTouchProcessor,
@NonNull SessionTracker sessionTracker,
- @NonNull AlternateBouncerInteractor alternateBouncerInteractor) {
+ @NonNull AlternateBouncerInteractor alternateBouncerInteractor,
+ @NonNull SecureSettings secureSettings) {
mContext = context;
mExecution = execution;
mVibrator = vibrator;
@@ -875,6 +878,7 @@
mBiometricExecutor = biometricsExecutor;
mPrimaryBouncerInteractor = primaryBouncerInteractor;
mAlternateBouncerInteractor = alternateBouncerInteractor;
+ mSecureSettings = secureSettings;
mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
? singlePointerTouchProcessor : null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 1b6c8c6..b4b3fae 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -61,6 +61,7 @@
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.settings.SecureSettings
private const val TAG = "UdfpsControllerOverlay"
@@ -90,6 +91,7 @@
private val keyguardStateController: KeyguardStateController,
private val unlockedScreenOffAnimationController: UnlockedScreenOffAnimationController,
private var udfpsDisplayModeProvider: UdfpsDisplayModeProvider,
+ private val secureSettings: SecureSettings,
val requestId: Long,
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
@@ -132,7 +134,7 @@
/** A helper if the [requestReason] was due to enrollment. */
val enrollHelper: UdfpsEnrollHelper? =
if (requestReason.isEnrollmentReason() && !shouldRemoveEnrollmentUi()) {
- UdfpsEnrollHelper(context, fingerprintManager, requestReason)
+ UdfpsEnrollHelper(context, fingerprintManager, secureSettings, requestReason)
} else {
null
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
index d5c763d3..cfa8ec5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java
@@ -24,11 +24,12 @@
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
import android.util.TypedValue;
import android.view.accessibility.AccessibilityManager;
+import com.android.systemui.util.settings.SecureSettings;
+
import java.util.ArrayList;
import java.util.List;
@@ -51,8 +52,8 @@
void onLastStepAcquired();
}
- @NonNull private final Context mContext;
@NonNull private final FingerprintManager mFingerprintManager;
+ @NonNull private final SecureSettings mSecureSettings;
// IUdfpsOverlayController reason
private final int mEnrollReason;
private final boolean mAccessibilityEnabled;
@@ -70,10 +71,11 @@
@Nullable Listener mListener;
public UdfpsEnrollHelper(@NonNull Context context,
- @NonNull FingerprintManager fingerprintManager, int reason) {
+ @NonNull FingerprintManager fingerprintManager, SecureSettings secureSettings,
+ int reason) {
- mContext = context;
mFingerprintManager = fingerprintManager;
+ mSecureSettings = secureSettings;
mEnrollReason = reason;
final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
@@ -84,8 +86,7 @@
// Number of pixels per mm
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1,
context.getResources().getDisplayMetrics());
- boolean useNewCoords = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- NEW_COORDS_OVERRIDE, 0,
+ boolean useNewCoords = mSecureSettings.getIntForUser(NEW_COORDS_OVERRIDE, 0,
UserHandle.USER_CURRENT) != 0;
if (useNewCoords && (Build.IS_ENG || Build.IS_USERDEBUG)) {
Log.v(TAG, "Using new coordinates");
@@ -210,8 +211,7 @@
float scale = SCALE;
if (Build.IS_ENG || Build.IS_USERDEBUG) {
- scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
- SCALE_OVERRIDE, SCALE,
+ scale = mSecureSettings.getFloatForUser(SCALE_OVERRIDE, SCALE,
UserHandle.USER_CURRENT);
}
final int index = mLocationsEnrolled - mCenterTouchCount;
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 58d40d3..4227a7a 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -25,13 +25,13 @@
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.os.RemoteException
-import android.os.UserHandle
import android.util.Log
import android.view.WindowManager
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.ActivityIntentHelper
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -55,6 +55,7 @@
private val cameraIntents: CameraIntentsWrapper,
private val contentResolver: ContentResolver,
@Main private val uiExecutor: Executor,
+ private val userTracker: UserTracker
) {
/**
* Whether the camera application can be launched for the camera launch gesture.
@@ -111,7 +112,7 @@
Intent.FLAG_ACTIVITY_NEW_TASK,
null,
activityOptions.toBundle(),
- UserHandle.CURRENT.identifier,
+ userTracker.userId,
)
} catch (e: RemoteException) {
Log.w(
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
index 867faf9..cc43e7e 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
@@ -20,15 +20,13 @@
import android.content.Intent
import android.provider.MediaStore
import android.text.TextUtils
-
import com.android.systemui.R
class CameraIntents {
companion object {
- val DEFAULT_SECURE_CAMERA_INTENT_ACTION =
- MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
- val DEFAULT_INSECURE_CAMERA_INTENT_ACTION =
- MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
+ val DEFAULT_SECURE_CAMERA_INTENT_ACTION = MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
+ val DEFAULT_INSECURE_CAMERA_INTENT_ACTION = MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA
+ private val VIDEO_CAMERA_INTENT_ACTION = MediaStore.INTENT_ACTION_VIDEO_CAMERA
const val EXTRA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"
@JvmStatic
@@ -44,18 +42,14 @@
@JvmStatic
fun getInsecureCameraIntent(context: Context): Intent {
val intent = Intent(DEFAULT_INSECURE_CAMERA_INTENT_ACTION)
- getOverrideCameraPackage(context)?.let {
- intent.setPackage(it)
- }
+ getOverrideCameraPackage(context)?.let { intent.setPackage(it) }
return intent
}
@JvmStatic
fun getSecureCameraIntent(context: Context): Intent {
val intent = Intent(DEFAULT_SECURE_CAMERA_INTENT_ACTION)
- getOverrideCameraPackage(context)?.let {
- intent.setPackage(it)
- }
+ getOverrideCameraPackage(context)?.let { intent.setPackage(it) }
return intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
}
@@ -68,5 +62,11 @@
fun isInsecureCameraIntent(intent: Intent?): Boolean {
return intent?.getAction()?.equals(DEFAULT_INSECURE_CAMERA_INTENT_ACTION) ?: false
}
+
+ /** Returns an [Intent] that can be used to start the camera in video mode. */
+ @JvmStatic
+ fun getVideoCameraIntent(): Intent {
+ return Intent(VIDEO_CAMERA_INTENT_ACTION)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
index cf02f8f..a434617 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
@@ -21,7 +21,9 @@
import javax.inject.Inject
/** Injectable wrapper around [CameraIntents]. */
-class CameraIntentsWrapper @Inject constructor(
+class CameraIntentsWrapper
+@Inject
+constructor(
private val context: Context,
) {
@@ -40,4 +42,9 @@
fun getInsecureCameraIntent(): Intent {
return CameraIntents.getInsecureCameraIntent(context)
}
+
+ /** Returns an [Intent] that can be used to start the camera in video mode. */
+ fun getVideoCameraIntent(): Intent {
+ return CameraIntents.getVideoCameraIntent()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index e38c89e..31cc0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -55,6 +55,7 @@
import com.android.systemui.navigationbar.NavigationBarComponent;
import com.android.systemui.notetask.NoteTaskModule;
import com.android.systemui.people.PeopleModule;
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
import com.android.systemui.privacy.PrivacyModule;
import com.android.systemui.qs.FgsManagerController;
@@ -211,6 +212,9 @@
abstract BcSmartspaceDataPlugin optionalBcSmartspaceDataPlugin();
@BindsOptionalOf
+ abstract BcSmartspaceConfigPlugin optionalBcSmartspaceConfigPlugin();
+
+ @BindsOptionalOf
abstract Recents optionalRecents();
@BindsOptionalOf
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 2a3d67f..c331164 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -17,12 +17,12 @@
package com.android.systemui.doze;
import android.hardware.display.AmbientDisplayConfiguration;
-import android.os.UserHandle;
import android.util.Log;
import com.android.systemui.dock.DockManager;
import com.android.systemui.doze.DozeMachine.State;
import com.android.systemui.doze.dagger.DozeScope;
+import com.android.systemui.settings.UserTracker;
import java.io.PrintWriter;
@@ -40,14 +40,17 @@
private final AmbientDisplayConfiguration mConfig;
private DozeMachine mMachine;
private final DockManager mDockManager;
+ private final UserTracker mUserTracker;
private final DockEventListener mDockEventListener;
private int mDockState = DockManager.STATE_NONE;
@Inject
- DozeDockHandler(AmbientDisplayConfiguration config, DockManager dockManager) {
+ DozeDockHandler(AmbientDisplayConfiguration config, DockManager dockManager,
+ UserTracker userTracker) {
mConfig = config;
mDockManager = dockManager;
+ mUserTracker = userTracker;
mDockEventListener = new DockEventListener();
}
@@ -100,7 +103,7 @@
nextState = State.DOZE_AOD_DOCKED;
break;
case DockManager.STATE_NONE:
- nextState = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) ? State.DOZE_AOD
+ nextState = mConfig.alwaysOnEnabled(mUserTracker.getUserId()) ? State.DOZE_AOD
: State.DOZE;
break;
case DockManager.STATE_DOCKED_HIDE:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 96c35d4..fc3263f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -23,7 +23,6 @@
import android.content.res.Configuration;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Trace;
-import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
@@ -33,6 +32,7 @@
import com.android.systemui.doze.dagger.WrappedService;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -149,6 +149,7 @@
private final DozeHost mDozeHost;
private final DockManager mDockManager;
private final Part[] mParts;
+ private final UserTracker mUserTracker;
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
private State mState = State.UNINITIALIZED;
@@ -161,7 +162,7 @@
AmbientDisplayConfiguration ambientDisplayConfig,
WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle,
DozeLog dozeLog, DockManager dockManager,
- DozeHost dozeHost, Part[] parts) {
+ DozeHost dozeHost, Part[] parts, UserTracker userTracker) {
mDozeService = service;
mAmbientDisplayConfig = ambientDisplayConfig;
mWakefulnessLifecycle = wakefulnessLifecycle;
@@ -170,6 +171,7 @@
mDockManager = dockManager;
mDozeHost = dozeHost;
mParts = parts;
+ mUserTracker = userTracker;
for (Part part : parts) {
part.setDozeMachine(this);
}
@@ -429,7 +431,7 @@
nextState = State.FINISH;
} else if (mDockManager.isDocked()) {
nextState = mDockManager.isHidden() ? State.DOZE : State.DOZE_AOD_DOCKED;
- } else if (mAmbientDisplayConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
+ } else if (mAmbientDisplayConfig.alwaysOnEnabled(mUserTracker.getUserId())) {
nextState = State.DOZE_AOD;
} else {
nextState = State.DOZE;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 937884c..4cade77 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.sensors.AsyncSensorManager;
+import com.android.systemui.util.settings.SystemSettings;
import java.io.PrintWriter;
import java.util.Objects;
@@ -78,6 +79,7 @@
private final DozeParameters mDozeParameters;
private final DevicePostureController mDevicePostureController;
private final DozeLog mDozeLog;
+ private final SystemSettings mSystemSettings;
private final int[] mSensorToBrightness;
private final int[] mSensorToScrimOpacity;
private final int mScreenBrightnessDim;
@@ -110,7 +112,8 @@
WakefulnessLifecycle wakefulnessLifecycle,
DozeParameters dozeParameters,
DevicePostureController devicePostureController,
- DozeLog dozeLog) {
+ DozeLog dozeLog,
+ SystemSettings systemSettings) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
@@ -122,6 +125,7 @@
mDozeHost = host;
mHandler = handler;
mDozeLog = dozeLog;
+ mSystemSettings = systemSettings;
mScreenBrightnessMinimumDimAmountFloat = context.getResources().getFloat(
R.dimen.config_screenBrightnessMinimumDimAmountFloat);
@@ -257,7 +261,7 @@
}
//TODO: brightnessfloat change usages to float.
private int clampToUserSetting(int brightness) {
- int userSetting = Settings.System.getIntForUser(mContext.getContentResolver(),
+ int userSetting = mSystemSettings.getIntForUser(
Settings.System.SCREEN_BRIGHTNESS, Integer.MAX_VALUE,
UserHandle.USER_CURRENT);
return Math.min(brightness, userSetting);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 72c7cf5..0d3503e 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -255,7 +255,7 @@
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
mConfig.wakeScreenGestureAvailable()
- && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT),
+ && mConfig.alwaysOnEnabled(mUserTracker.getUserId()),
DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE,
false /* reports touch coordinates */,
false /* touchscreen */
@@ -296,7 +296,7 @@
private boolean udfpsLongPressConfigured() {
return mUdfpsEnrolled
- && (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) || mScreenOffUdfpsEnabled);
+ && (mConfig.alwaysOnEnabled(mUserTracker.getUserId()) || mScreenOffUdfpsEnabled);
}
private boolean quickPickUpConfigured() {
@@ -697,13 +697,13 @@
}
protected boolean enabledBySetting() {
- if (!mConfig.enabled(UserHandle.USER_CURRENT)) {
+ if (!mConfig.enabled(mUserTracker.getUserId())) {
return false;
} else if (TextUtils.isEmpty(mSetting)) {
return true;
}
return mSecureSettings.getIntForUser(mSetting, mSettingDefault ? 1 : 0,
- UserHandle.USER_CURRENT) != 0;
+ mUserTracker.getUserId()) != 0;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
index e6d9865..de0bdd3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
@@ -20,10 +20,10 @@
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.PowerManager;
-import android.os.UserHandle;
import android.text.TextUtils;
import com.android.systemui.doze.dagger.DozeScope;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import java.io.PrintWriter;
@@ -57,6 +57,7 @@
private final AmbientDisplayConfiguration mConfig;
private final DozeLog mDozeLog;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+ private final UserTracker mUserTracker;
private boolean mIsCarModeEnabled = false;
@@ -65,11 +66,13 @@
DozeHost dozeHost,
AmbientDisplayConfiguration config,
DozeLog dozeLog,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy) {
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ UserTracker userTracker) {
mDozeHost = dozeHost;
mConfig = config;
mDozeLog = dozeLog;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+ mUserTracker = userTracker;
}
@Override
@@ -148,7 +151,7 @@
private void handleCarModeExited() {
mDozeLog.traceCarModeEnded();
- mMachine.requestState(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)
+ mMachine.requestState(mConfig.alwaysOnEnabled(mUserTracker.getUserId())
? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE);
}
@@ -166,7 +169,7 @@
if (mDozeHost.isPowerSaveActive()) {
nextState = DozeMachine.State.DOZE;
} else if (mMachine.getState() == DozeMachine.State.DOZE
- && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
+ && mConfig.alwaysOnEnabled(mUserTracker.getUserId())) {
nextState = DozeMachine.State.DOZE_AOD;
}
@@ -181,7 +184,7 @@
// handles suppression changes, while DozeMachine#transitionPolicy handles gating
// transitions to DOZE_AOD
final DozeMachine.State nextState;
- if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !suppressed) {
+ if (mConfig.alwaysOnEnabled(mUserTracker.getUserId()) && !suppressed) {
nextState = DozeMachine.State.DOZE_AOD;
} else {
nextState = DozeMachine.State.DOZE;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index fdc115b..27641fe 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -234,6 +234,13 @@
});
}
+ @Override
+ public void onEndDream() {
+ mExecutor.execute(() -> {
+ resetCurrentDreamOverlayLocked();
+ });
+ }
+
private Lifecycle.State getCurrentStateLocked() {
return mLifecycleRegistry.getCurrentState();
}
@@ -317,6 +324,7 @@
mDreamOverlayContainerViewController = null;
mDreamOverlayTouchMonitor = null;
+ mWindow = null;
mStarted = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index f1bb156..90c440c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -25,7 +25,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.os.UserHandle;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.PluralsMessageFormatter;
@@ -37,6 +36,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -72,6 +72,7 @@
mDreamOverlayNotificationCountProvider;
private final ZenModeController mZenModeController;
private final DreamOverlayStateController mDreamOverlayStateController;
+ private final UserTracker mUserTracker;
private final StatusBarWindowStateController mStatusBarWindowStateController;
private final DreamOverlayStatusBarItemsProvider mStatusBarItemsProvider;
private final Executor mMainExecutor;
@@ -154,7 +155,8 @@
ZenModeController zenModeController,
StatusBarWindowStateController statusBarWindowStateController,
DreamOverlayStatusBarItemsProvider statusBarItemsProvider,
- DreamOverlayStateController dreamOverlayStateController) {
+ DreamOverlayStateController dreamOverlayStateController,
+ UserTracker userTracker) {
super(view);
mResources = resources;
mMainExecutor = mainExecutor;
@@ -169,6 +171,7 @@
mStatusBarItemsProvider = statusBarItemsProvider;
mZenModeController = zenModeController;
mDreamOverlayStateController = dreamOverlayStateController;
+ mUserTracker = userTracker;
// Register to receive show/hide updates for the system status bar. Our custom status bar
// needs to hide when the system status bar is showing to ovoid overlapping status bars.
@@ -259,7 +262,7 @@
private void updateAlarmStatusIcon() {
final AlarmManager.AlarmClockInfo alarm =
- mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
+ mAlarmManager.getNextAlarmClock(mUserTracker.getUserId());
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
showIcon(
DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index c45c8e7..5d85fc96 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -64,6 +64,10 @@
// TODO(b/259130119): Tracking Bug
val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
+ // TODO(b/265804648): Tracking Bug
+ @JvmField
+ val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
+
// TODO(b/254512538): Tracking Bug
val INSTANT_VOICE_REPLY = unreleasedFlag(111, "instant_voice_reply", teamfood = true)
@@ -102,6 +106,11 @@
val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true)
+ // TODO(b/263414400): Tracking Bug
+ @JvmField
+ val NOTIFICATION_ANIMATE_BIG_PICTURE =
+ unreleasedFlag(120, "notification_animate_big_picture", teamfood = true)
+
// 200 - keyguard/lockscreen
// ** Flag retired **
// public static final BooleanFlag KEYGUARD_LAYOUT =
@@ -175,7 +184,7 @@
* of the Alternate/Authentication Bouncer. No visual UI changes.
*/
// TODO(b/260619425): Tracking Bug
- @JvmField val MODERN_ALTERNATE_BOUNCER = unreleasedFlag(219, "modern_alternate_bouncer")
+ @JvmField val MODERN_ALTERNATE_BOUNCER = releasedFlag(219, "modern_alternate_bouncer")
/** Flag to control the migration of face auth to modern architecture. */
// TODO(b/262838215): Tracking bug
@@ -335,6 +344,10 @@
// TODO(b/263512203): Tracking Bug
val MEDIA_EXPLICIT_INDICATOR = unreleasedFlag(911, "media_explicit_indicator", teamfood = true)
+ // TODO(b/265813373): Tracking Bug
+ val MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE =
+ unreleasedFlag(912, "media_ttt_dismiss_gesture", teamfood = true)
+
// 1000 - dock
val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
@@ -529,6 +542,18 @@
val OUTPUT_SWITCHER_SHOW_API_ENABLED =
unreleasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
+ // 2700 - unfold transitions
+ // TODO(b/265764985): Tracking Bug
+ @Keep
+ @JvmField
+ val ENABLE_DARK_VIGNETTE_WHEN_FOLDING =
+ unreleasedFlag(2700, "enable_dark_vignette_when_folding")
+
// TODO(b259590361): Tracking bug
val EXPERIMENTAL_FLAG = unreleasedFlag(2, "exp_flag_release")
+
+ // 2600 - keyboard shortcut
+ // TODO(b/259352579): Tracking Bug
+ @JvmField
+ val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index c3e163f..949bcfb 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -21,7 +21,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
-import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
@@ -731,9 +730,10 @@
}
@VisibleForTesting
- boolean shouldDisplayBugReport(UserInfo currentUser) {
- return mGlobalSettings.getInt(Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0
- && (currentUser == null || currentUser.isAdmin());
+ boolean shouldDisplayBugReport(@Nullable UserInfo user) {
+ return user != null && user.isAdmin()
+ && mGlobalSettings.getIntForUser(Settings.Secure.BUGREPORT_IN_POWER_MENU, 0,
+ user.id) != 0;
}
@Override
@@ -901,7 +901,7 @@
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ mContext.startActivityAsUser(intent, mUserTracker.getUserHandle());
}
}
}
@@ -959,8 +959,7 @@
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN,
- SCREENSHOT_GLOBAL_ACTIONS, mHandler, null);
+ mScreenshotHelper.takeScreenshot(SCREENSHOT_GLOBAL_ACTIONS, mHandler, null);
mMetricsLogger.action(MetricsEvent.ACTION_SCREENSHOT_POWER_MENU);
mUiEventLogger.log(GlobalActionsEvent.GA_SCREENSHOT_PRESS);
}
@@ -1059,7 +1058,7 @@
@Override
public boolean showBeforeProvisioning() {
return Build.isDebuggable() && mGlobalSettings.getIntForUser(
- Settings.Global.BUGREPORT_IN_POWER_MENU, 0, getCurrentUser().id) != 0
+ Settings.Secure.BUGREPORT_IN_POWER_MENU, 0, getCurrentUser().id) != 0
&& getCurrentUser().isAdmin();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 4f1a2b3..ad7973e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -24,7 +24,6 @@
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.input.InputManager;
@@ -53,6 +52,7 @@
import com.android.systemui.CoreStartable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -108,6 +108,7 @@
protected volatile Context mContext;
private final Provider<LocalBluetoothManager> mBluetoothManagerProvider;
+ private final SecureSettings mSecureSettings;
private boolean mEnabled;
private String mKeyboardName;
@@ -125,9 +126,11 @@
private int mState;
@Inject
- public KeyboardUI(Context context, Provider<LocalBluetoothManager> bluetoothManagerProvider) {
+ public KeyboardUI(Context context, Provider<LocalBluetoothManager> bluetoothManagerProvider,
+ SecureSettings secureSettings) {
mContext = context;
this.mBluetoothManagerProvider = bluetoothManagerProvider;
+ mSecureSettings = secureSettings;
}
@Override
@@ -298,9 +301,8 @@
}
private boolean isUserSetupComplete() {
- ContentResolver resolver = mContext.getContentResolver();
- return Secure.getIntForUser(
- resolver, Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+ return mSecureSettings.getIntForUser(
+ Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
}
private CachedBluetoothDevice getPairedKeyboard() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 18854e5..0dbc930 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -148,12 +148,12 @@
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.DeviceConfigProxy;
+import dagger.Lazy;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.concurrent.Executor;
-import dagger.Lazy;
-
/**
* Mediates requests related to the keyguard. This includes queries about the
* state of the keyguard, power management events that effect whether the keyguard
@@ -589,12 +589,6 @@
@Override
public void onDeviceProvisioned() {
sendUserPresentBroadcast();
- synchronized (KeyguardViewMediator.this) {
- // If system user is provisioned, we might want to lock now to avoid showing launcher
- if (mustNotUnlockCurrentUser()) {
- doKeyguardLocked(null);
- }
- }
}
@Override
@@ -1265,11 +1259,6 @@
mPM.userActivity(SystemClock.uptimeMillis(), false);
}
- boolean mustNotUnlockCurrentUser() {
- return UserManager.isSplitSystemUser()
- && KeyguardUpdateMonitor.getCurrentUser() == UserHandle.USER_SYSTEM;
- }
-
private void setupLocked() {
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
mShowKeyguardWakeLock.setReferenceCounted(false);
@@ -1342,7 +1331,7 @@
mHideAnimation = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.lock_screen_behind_enter);
- mWorkLockController = new WorkLockActivityController(mContext);
+ mWorkLockController = new WorkLockActivityController(mContext, mUserTracker);
}
@Override
@@ -1947,31 +1936,28 @@
}
}
- // In split system user mode, we never unlock system user.
- if (!mustNotUnlockCurrentUser()
- || !mUpdateMonitor.isDeviceProvisioned()) {
+ // if the setup wizard hasn't run yet, don't show
+ final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
+ final boolean absent = SubscriptionManager.isValidSubscriptionId(
+ mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_ABSENT));
+ final boolean disabled = SubscriptionManager.isValidSubscriptionId(
+ mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PERM_DISABLED));
+ final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
+ || ((absent || disabled) && requireSim);
- // if the setup wizard hasn't run yet, don't show
- final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
- final boolean absent = SubscriptionManager.isValidSubscriptionId(
- mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_ABSENT));
- final boolean disabled = SubscriptionManager.isValidSubscriptionId(
- mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PERM_DISABLED));
- final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
- || ((absent || disabled) && requireSim);
-
- if (!lockedOrMissing && shouldWaitForProvisioning()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
- + " and the sim is not locked or missing");
- return;
+ if (!lockedOrMissing && shouldWaitForProvisioning()) {
+ if (DEBUG) {
+ Log.d(TAG, "doKeyguard: not showing because device isn't provisioned and the sim is"
+ + " not locked or missing");
}
+ return;
+ }
- boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
- if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
- && !lockedOrMissing && !forceShow) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
- return;
- }
+ boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
+ if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
+ && !lockedOrMissing && !forceShow) {
+ if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+ return;
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
@@ -2289,6 +2275,10 @@
}
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();
+ } else if (mSurfaceBehindRemoteAnimationRunning) {
+ // We're already running the keyguard exit animation, likely due to an in-progress swipe
+ // to unlock.
+ exitKeyguardAndFinishSurfaceBehindRemoteAnimation(false /* cancelled */);
} else if (!mHideAnimationRun) {
if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
mHideAnimationRun = true;
@@ -2539,15 +2529,6 @@
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleHide");
- if (mustNotUnlockCurrentUser()) {
- // In split system user mode, we never unlock system user. The end user has to
- // switch to another user.
- // TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
- // still completes and makes the screen blank.
- if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
- mKeyguardExitAnimationRunner = null;
- return;
- }
mHiding = true;
if (mShowing && !mOccluded) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 16817ed..b92499e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -26,10 +26,10 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -37,16 +37,20 @@
private static final String TAG = WorkLockActivityController.class.getSimpleName();
private final Context mContext;
+ private final UserTracker mUserTracker;
private final IActivityTaskManager mIatm;
- public WorkLockActivityController(Context context) {
- this(context, TaskStackChangeListeners.getInstance(), ActivityTaskManager.getService());
+ public WorkLockActivityController(Context context, UserTracker userTracker) {
+ this(context, userTracker, TaskStackChangeListeners.getInstance(),
+ ActivityTaskManager.getService());
}
@VisibleForTesting
WorkLockActivityController(
- Context context, TaskStackChangeListeners tscl, IActivityTaskManager iAtm) {
+ Context context, UserTracker userTracker, TaskStackChangeListeners tscl,
+ IActivityTaskManager iAtm) {
mContext = context;
+ mUserTracker = userTracker;
mIatm = iAtm;
tscl.registerTaskStackListener(mLockListener);
@@ -65,7 +69,8 @@
options.setLaunchTaskId(info.taskId);
options.setTaskOverlay(true, false /* canResume */);
- final int result = startActivityAsUser(intent, options.toBundle(), UserHandle.USER_CURRENT);
+ final int result = startActivityAsUser(intent, options.toBundle(),
+ mUserTracker.getUserId());
if (ActivityManager.isStartResultSuccessful(result)) {
// OK
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
index ea5b4f4..76c2430 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt
@@ -25,10 +25,12 @@
object BuiltInKeyguardQuickAffordanceKeys {
// Please keep alphabetical order of const names to simplify future maintenance.
const val CAMERA = "camera"
+ const val CREATE_NOTE = "create_note"
const val DO_NOT_DISTURB = "do_not_disturb"
const val FLASHLIGHT = "flashlight"
const val HOME_CONTROLS = "home"
const val QR_CODE_SCANNER = "qr_code_scanner"
const val QUICK_ACCESS_WALLET = "wallet"
+ const val VIDEO_CAMERA = "video_camera"
// Please keep alphabetical order of const names to simplify future maintenance.
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
index dbc376e..f6e6d6b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
@@ -26,6 +26,7 @@
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.StatusBarState
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -46,7 +47,7 @@
get() = context.getString(R.string.accessibility_camera_button)
override val pickerIconResourceId: Int
- get() = com.android.internal.R.drawable.perm_group_camera
+ get() = R.drawable.ic_camera
override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
get() =
@@ -54,12 +55,20 @@
KeyguardQuickAffordanceConfig.LockScreenState.Visible(
icon =
Icon.Resource(
- com.android.internal.R.drawable.perm_group_camera,
+ R.drawable.ic_camera,
ContentDescription.Resource(R.string.accessibility_camera_button)
)
)
)
+ override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
+ return if (isLaunchable()) {
+ super.getPickerScreenState()
+ } else {
+ KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
+ }
+ }
+
override fun onTriggered(
expandable: Expandable?
): KeyguardQuickAffordanceConfig.OnTriggeredResult {
@@ -68,4 +77,8 @@
.launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
}
+
+ private fun isLaunchable(): Boolean {
+ return cameraGestureHelper.get().canCameraGestureBeLaunched(StatusBarState.KEYGUARD)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index ed1ff32..be73f85 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -128,7 +128,7 @@
awaitClose { controller.removeCallback(callback) }
},
secureSettings
- .observerFlow(Settings.Secure.ZEN_DURATION)
+ .observerFlow(userTracker.userId, Settings.Secure.ZEN_DURATION)
.onStart { emit(Unit) }
.map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) }
.flowOn(backgroundDispatcher)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
index 71d01eb..a1cce5c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt
@@ -39,6 +39,7 @@
quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig,
qrCodeScanner: QrCodeScannerKeyguardQuickAffordanceConfig,
camera: CameraQuickAffordanceConfig,
+ videoCamera: VideoCameraQuickAffordanceConfig,
): Set<KeyguardQuickAffordanceConfig> {
return setOf(
camera,
@@ -47,6 +48,7 @@
home,
quickAccessWallet,
qrCodeScanner,
+ videoCamera,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index 680c06b..4ba2eb9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -100,9 +100,9 @@
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
return when {
- !walletController.isWalletEnabled ->
+ !walletController.walletClient.isWalletServiceAvailable ->
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
- walletController.walletClient.tileIcon == null || queryCards().isEmpty() -> {
+ !walletController.isWalletEnabled || queryCards().isEmpty() -> {
val componentName =
walletController.walletClient.createWalletSettingsIntent().toComponentName()
val actionText =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt
new file mode 100644
index 0000000..d9ec3b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfig.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.keyguard.data.quickaffordance
+
+import android.app.StatusBarManager
+import android.content.Context
+import android.content.Intent
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.R
+import com.android.systemui.animation.Expandable
+import com.android.systemui.camera.CameraIntents
+import com.android.systemui.camera.CameraIntentsWrapper
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.settings.UserTracker
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
+
+@SysUISingleton
+class VideoCameraQuickAffordanceConfig
+@Inject
+constructor(
+ @Application private val context: Context,
+ private val cameraIntents: CameraIntentsWrapper,
+ private val activityIntentHelper: ActivityIntentHelper,
+ private val userTracker: UserTracker,
+) : KeyguardQuickAffordanceConfig {
+
+ private val intent: Intent by lazy {
+ cameraIntents.getVideoCameraIntent().apply {
+ putExtra(
+ CameraIntents.EXTRA_LAUNCH_SOURCE,
+ StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE,
+ )
+ }
+ }
+
+ override val key: String
+ get() = BuiltInKeyguardQuickAffordanceKeys.VIDEO_CAMERA
+
+ override val pickerName: String
+ get() = context.getString(R.string.video_camera)
+
+ override val pickerIconResourceId: Int
+ get() = R.drawable.ic_videocam
+
+ override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
+ get() =
+ flowOf(
+ if (isLaunchable()) {
+ KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+ icon =
+ Icon.Resource(
+ R.drawable.ic_videocam,
+ ContentDescription.Resource(R.string.video_camera)
+ )
+ )
+ } else {
+ KeyguardQuickAffordanceConfig.LockScreenState.Hidden
+ }
+ )
+
+ override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
+ return if (isLaunchable()) {
+ super.getPickerScreenState()
+ } else {
+ KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
+ }
+ }
+
+ override fun onTriggered(
+ expandable: Expandable?
+ ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
+ return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity(
+ intent = intent,
+ canShowWhileLocked = false,
+ )
+ }
+
+ private fun isLaunchable(): Boolean {
+ return activityIntentHelper.getTargetActivityInfo(
+ intent,
+ userTracker.userId,
+ true,
+ ) != null
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
new file mode 100644
index 0000000..08edbc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.hardware.biometrics.BiometricSourceType
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Encapsulates state about device entry fingerprint auth mechanism. */
+interface DeviceEntryFingerprintAuthRepository {
+ /** Whether the device entry fingerprint auth is locked out. */
+ val isLockedOut: Flow<Boolean>
+}
+
+/**
+ * Implementation of [DeviceEntryFingerprintAuthRepository] that uses [KeyguardUpdateMonitor] as the
+ * source of truth.
+ *
+ * Dependency on [KeyguardUpdateMonitor] will be removed once fingerprint auth state is moved out of
+ * [KeyguardUpdateMonitor]
+ */
+@SysUISingleton
+class DeviceEntryFingerprintAuthRepositoryImpl
+@Inject
+constructor(
+ val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+) : DeviceEntryFingerprintAuthRepository {
+
+ override val isLockedOut: Flow<Boolean> = conflatedCallbackFlow {
+ val sendLockoutUpdate =
+ fun() {
+ trySendWithFailureLogging(
+ keyguardUpdateMonitor.isFingerprintLockedOut,
+ TAG,
+ "onLockedOutStateChanged"
+ )
+ }
+ val callback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType?) {
+ if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
+ sendLockoutUpdate()
+ }
+ }
+ }
+ keyguardUpdateMonitor.registerCallback(callback)
+ sendLockoutUpdate()
+ awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
+ }
+
+ companion object {
+ const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
new file mode 100644
index 0000000..d90f328
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/TrustRepository.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.app.trust.TrustManager
+import com.android.keyguard.logging.TrustRepositoryLogger
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.shared.model.TrustModel
+import com.android.systemui.user.data.repository.UserRepository
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.shareIn
+
+/** Encapsulates any state relevant to trust agents and trust grants. */
+interface TrustRepository {
+ /** Flow representing whether the current user is trusted. */
+ val isCurrentUserTrusted: Flow<Boolean>
+}
+
+@SysUISingleton
+class TrustRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val userRepository: UserRepository,
+ private val trustManager: TrustManager,
+ private val logger: TrustRepositoryLogger,
+) : TrustRepository {
+ private val latestTrustModelForUser = mutableMapOf<Int, TrustModel>()
+
+ private val trust =
+ conflatedCallbackFlow {
+ val callback =
+ object : TrustManager.TrustListener {
+ override fun onTrustChanged(
+ enabled: Boolean,
+ newlyUnlocked: Boolean,
+ userId: Int,
+ flags: Int,
+ grantMsgs: List<String>?
+ ) {
+ logger.onTrustChanged(enabled, newlyUnlocked, userId, flags, grantMsgs)
+ trySendWithFailureLogging(
+ TrustModel(enabled, userId),
+ TrustRepositoryLogger.TAG,
+ "onTrustChanged"
+ )
+ }
+
+ override fun onTrustError(message: CharSequence?) = Unit
+
+ override fun onTrustManagedChanged(enabled: Boolean, userId: Int) = Unit
+ }
+ trustManager.registerTrustListener(callback)
+ logger.trustListenerRegistered()
+ awaitClose {
+ logger.trustListenerUnregistered()
+ trustManager.unregisterTrustListener(callback)
+ }
+ }
+ .onEach {
+ latestTrustModelForUser[it.userId] = it
+ logger.trustModelEmitted(it)
+ }
+ .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
+
+ override val isCurrentUserTrusted: Flow<Boolean>
+ get() =
+ combine(trust, userRepository.selectedUserInfo, ::Pair)
+ .map { latestTrustModelForUser[it.second.id]?.isTrusted ?: false }
+ .distinctUntilChanged()
+ .onEach { logger.isCurrentUserTrusted(it) }
+ .onStart { emit(false) }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 7134ec0..81a5828 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -31,8 +31,10 @@
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@SysUISingleton
@@ -87,6 +89,9 @@
private fun listenForDreamingToOccluded() {
scope.launch {
keyguardInteractor.isDreaming
+ // Add a slight delay, as dreaming and occluded events will arrive with a small gap
+ // in time. This prevents a transition to OCCLUSION happening prematurely.
+ .onEach { delay(50) }
.sample(
combine(
keyguardInteractor.isKeyguardOccluded,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index 9203a9b..14f918d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -50,10 +50,9 @@
private fun listenForGoneToDreaming() {
scope.launch {
keyguardInteractor.isAbleToDream
- .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
- .collect { pair ->
- val (isAbleToDream, keyguardState) = pair
- if (isAbleToDream && keyguardState == KeyguardState.GONE) {
+ .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+ .collect { (isAbleToDream, lastStartedStep) ->
+ if (isAbleToDream && lastStartedStep.to == KeyguardState.GONE) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
@@ -72,15 +71,15 @@
keyguardInteractor.wakefulnessModel
.sample(
combine(
- keyguardTransitionInteractor.finishedKeyguardState,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep,
keyguardInteractor.isAodAvailable,
::Pair
),
::toTriple
)
- .collect { (wakefulnessState, keyguardState, isAodAvailable) ->
+ .collect { (wakefulnessState, lastStartedStep, isAodAvailable) ->
if (
- keyguardState == KeyguardState.GONE &&
+ lastStartedStep.to == KeyguardState.GONE &&
wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP
) {
keyguardTransitionRepository.startTransition(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index a92540d..6679b22 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -20,8 +20,6 @@
import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
-import android.os.UserHandle
-import android.os.UserManager
import android.view.View
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
@@ -134,12 +132,6 @@
return
}
- val keyguardUserId = KeyguardUpdateMonitor.getCurrentUser()
- if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
- // In split system user mode, we never unlock system user.
- return
- }
-
Trace.beginSection("KeyguardBouncer#show")
repository.setPrimaryScrimmed(isScrimmed)
if (isScrimmed) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TrustModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TrustModel.kt
new file mode 100644
index 0000000..4fd14b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/TrustModel.kt
@@ -0,0 +1,25 @@
+/*
+ * 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.keyguard.shared.model
+
+/** Represents the trust state */
+data class TrustModel(
+ /** If true, the system believes the environment to be trusted. */
+ val isTrusted: Boolean,
+ /** The user, for which the trust changed. */
+ val userId: Int,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
index 9d8bf7d..d020529 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt
@@ -342,14 +342,12 @@
private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
private var longPressAnimator: ViewPropertyAnimator? = null
- private var downTimestamp = 0L
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
return when (event?.actionMasked) {
MotionEvent.ACTION_DOWN ->
if (viewModel.configKey != null) {
- downTimestamp = System.currentTimeMillis()
longPressAnimator =
view
.animate()
@@ -396,7 +394,7 @@
MotionEvent.ACTION_UP -> {
cancel(
onAnimationEnd =
- if (System.currentTimeMillis() - downTimestamp < longPressDurationMs) {
+ if (event.eventTime - event.downTime < longPressDurationMs) {
Runnable {
messageDisplayer.invoke(
R.string.keyguard_affordance_press_too_short
@@ -437,7 +435,6 @@
}
private fun cancel(onAnimationEnd: Runnable? = null) {
- downTimestamp = 0L
longPressAnimator?.cancel()
longPressAnimator = null
view.animate().scaleX(1f).scaleY(1f).withEndAction(onAnimationEnd)
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index afbd8ed..e3c44d1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -191,15 +191,12 @@
false /* systrace */);
}
- /**
- * Provides a logging buffer for logs related to swiping away the status bar while in immersive
- * mode. See {@link com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureLogger}.
- */
+ /** Provides a logging buffer for logs related to swipe up gestures. */
@Provides
@SysUISingleton
- @SwipeStatusBarAwayLog
- public static LogBuffer provideSwipeAwayGestureLogBuffer(LogBufferFactory factory) {
- return factory.create("SwipeStatusBarAwayLog", 30);
+ @SwipeUpLog
+ public static LogBuffer provideSwipeUpLogBuffer(LogBufferFactory factory) {
+ return factory.create("SwipeUpLog", 30);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeStatusBarAwayLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
similarity index 88%
rename from packages/SystemUI/src/com/android/systemui/log/dagger/SwipeStatusBarAwayLog.java
rename to packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
index 4c276e2..d58b538 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeStatusBarAwayLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
@@ -27,10 +27,10 @@
/**
* A {@link LogBuffer} for
- * {@link com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureLogger}.
+ * {@link com.android.systemui.statusbar.gesture.SwipeUpGestureLogger}.
*/
@Qualifier
@Documented
@Retention(RUNTIME)
-public @interface SwipeStatusBarAwayLog {
+public @interface SwipeUpLog {
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 93be6a7..5c65c8b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -162,8 +162,8 @@
context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
UI_MODE_NIGHT_YES
)
- colorScheme.accent1[2]
- else colorScheme.accent1[3]
+ colorScheme.accent1.s100
+ else colorScheme.accent1.s200
},
{ seamlessColor: Int ->
val accentColorList = ColorStateList.valueOf(seamlessColor)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaColorSchemes.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaColorSchemes.kt
index 82abf9b..2a8362b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaColorSchemes.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaColorSchemes.kt
@@ -19,28 +19,28 @@
import com.android.systemui.monet.ColorScheme
/** Returns the surface color for media controls based on the scheme. */
-internal fun surfaceFromScheme(scheme: ColorScheme) = scheme.accent2[9] // A2-800
+internal fun surfaceFromScheme(scheme: ColorScheme) = scheme.accent2.s800 // A2-800
/** Returns the primary accent color for media controls based on the scheme. */
-internal fun accentPrimaryFromScheme(scheme: ColorScheme) = scheme.accent1[2] // A1-100
+internal fun accentPrimaryFromScheme(scheme: ColorScheme) = scheme.accent1.s100 // A1-100
/** Returns the secondary accent color for media controls based on the scheme. */
-internal fun accentSecondaryFromScheme(scheme: ColorScheme) = scheme.accent1[3] // A1-200
+internal fun accentSecondaryFromScheme(scheme: ColorScheme) = scheme.accent1.s200 // A1-200
/** Returns the primary text color for media controls based on the scheme. */
-internal fun textPrimaryFromScheme(scheme: ColorScheme) = scheme.neutral1[1] // N1-50
+internal fun textPrimaryFromScheme(scheme: ColorScheme) = scheme.neutral1.s50 // N1-50
/** Returns the inverse of the primary text color for media controls based on the scheme. */
-internal fun textPrimaryInverseFromScheme(scheme: ColorScheme) = scheme.neutral1[10] // N1-900
+internal fun textPrimaryInverseFromScheme(scheme: ColorScheme) = scheme.neutral1.s900 // N1-900
/** Returns the secondary text color for media controls based on the scheme. */
-internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2[3] // N2-200
+internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s200 // N2-200
/** Returns the tertiary text color for media controls based on the scheme. */
-internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2[5] // N2-400
+internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s400 // N2-400
/** Returns the color for the start of the background gradient based on the scheme. */
-internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2[8] // A2-700
+internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2.s700 // A2-700
/** Returns the color for the end of the background gradient based on the scheme. */
-internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1[8] // A1-700
+internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1.s700 // A1-700
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 51b5a3d..d6c6a81 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,17 +16,24 @@
package com.android.systemui.media.dialog;
+import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED;
+
+import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
+import android.media.RouteListingPreference;
+import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
+import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import androidx.core.widget.CompoundButtonCompat;
import androidx.recyclerview.widget.RecyclerView;
@@ -186,6 +193,17 @@
mCurrentActivePosition = position;
updateFullItemClickListener(v -> onItemClick(v, device));
setSingleLineLayout(getItemTitle(device));
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+ && mController.isSubStatusSupported() && device.hasDisabledReason()) {
+ //update to subtext with device status
+ setUpDeviceIcon(device);
+ mSubTitleText.setText(
+ Api34Impl.composeDisabledReason(device.getDisableReason(), mContext));
+ updateConnectionFailedStatusIcon();
+ updateFullItemClickListener(null);
+ setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */,
+ false /* showProgressBar */, true /* showSubtitle */,
+ true /* showStatus */);
} else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
setUpDeviceIcon(device);
updateConnectionFailedStatusIcon();
@@ -389,4 +407,17 @@
mTitleText.setText(groupDividerTitle);
}
}
+
+ @RequiresApi(34)
+ private static class Api34Impl {
+ @DoNotInline
+ static String composeDisabledReason(@RouteListingPreference.Item.DisableReason int reason,
+ Context context) {
+ switch(reason) {
+ case DISABLE_REASON_SUBSCRIPTION_REQUIRED:
+ return context.getString(R.string.media_output_status_require_premium);
+ }
+ return "";
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 7bc0c0c..9cf672b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -493,20 +493,20 @@
ColorScheme mCurrentColorScheme = new ColorScheme(wallpaperColors,
isDarkTheme);
if (isDarkTheme) {
- mColorItemContent = mCurrentColorScheme.getAccent1().get(2); // A1-100
- mColorSeekbarProgress = mCurrentColorScheme.getAccent2().get(7); // A2-600
- mColorButtonBackground = mCurrentColorScheme.getAccent1().get(4); // A1-300
- mColorItemBackground = mCurrentColorScheme.getNeutral2().get(9); // N2-800
- mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().get(9); // A2-800
- mColorPositiveButtonText = mCurrentColorScheme.getAccent2().get(9); // A2-800
- mColorDialogBackground = mCurrentColorScheme.getNeutral1().get(10); // N1-900
+ mColorItemContent = mCurrentColorScheme.getAccent1().getS100(); // A1-100
+ mColorSeekbarProgress = mCurrentColorScheme.getAccent2().getS600(); // A2-600
+ mColorButtonBackground = mCurrentColorScheme.getAccent1().getS300(); // A1-300
+ mColorItemBackground = mCurrentColorScheme.getNeutral2().getS800(); // N2-800
+ mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().getS800(); // A2-800
+ mColorPositiveButtonText = mCurrentColorScheme.getAccent2().getS800(); // A2-800
+ mColorDialogBackground = mCurrentColorScheme.getNeutral1().getS900(); // N1-900
} else {
- mColorItemContent = mCurrentColorScheme.getAccent1().get(9); // A1-800
- mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(4); // A1-300
- mColorButtonBackground = mCurrentColorScheme.getAccent1().get(7); // A1-600
- mColorItemBackground = mCurrentColorScheme.getAccent2().get(1); // A2-50
- mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().get(2); // A1-100
- mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().get(1); // N1-50
+ mColorItemContent = mCurrentColorScheme.getAccent1().getS800(); // A1-800
+ mColorSeekbarProgress = mCurrentColorScheme.getAccent1().getS300(); // A1-300
+ mColorButtonBackground = mCurrentColorScheme.getAccent1().getS600(); // A1-600
+ mColorItemBackground = mCurrentColorScheme.getAccent2().getS50(); // A2-50
+ mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().getS100(); // A1-100
+ mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().getS50(); // N1-50
mColorDialogBackground = mCurrentColorScheme.getBackgroundColor();
}
}
@@ -748,6 +748,10 @@
return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_ROUTES_PROCESSING);
}
+ public boolean isSubStatusSupported() {
+ return mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_DEVICE_STATUS);
+ }
+
List<MediaDevice> getGroupMediaDevices() {
final List<MediaDevice> selectedDevices = getSelectedMediaDevice();
final List<MediaDevice> selectableDevices = getSelectableMediaDevice();
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
index 8a565fa..60504e4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
@@ -30,4 +30,8 @@
/** Check whether the flag for the receiver success state is enabled. */
fun isMediaTttReceiverSuccessRippleEnabled(): Boolean =
featureFlags.isEnabled(Flags.MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE)
+
+ /** True if the media transfer chip can be dismissed via a gesture. */
+ fun isMediaTttDismissGestureEnabled(): Boolean =
+ featureFlags.isEnabled(Flags.MEDIA_TAP_TO_TRANSFER_DISMISS_GESTURE)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
index 935f38d..902a10a0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinator.kt
@@ -30,6 +30,7 @@
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttUtils
import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
import com.android.systemui.temporarydisplay.ViewPriority
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.temporarydisplay.chipbar.ChipbarEndItem
@@ -54,6 +55,7 @@
private var displayedState: ChipStateSender? = null
// A map to store current chip state per id.
+ // TODO(b/265455911): Log whenever we add or remove from the store.
private var stateMap: MutableMap<String, ChipStateSender> = mutableMapOf()
private val commandQueueCallbacks =
@@ -102,10 +104,9 @@
}
uiEventLogger.logSenderStateChange(chipState)
- stateMap.put(routeInfo.id, chipState)
if (chipState == ChipStateSender.FAR_FROM_RECEIVER) {
// No need to store the state since it is the default state
- stateMap.remove(routeInfo.id)
+ removeIdFromStore(routeInfo.id)
// Return early if we're not displaying a chip anyway
val currentDisplayedState = displayedState ?: return
@@ -126,7 +127,9 @@
displayedState = null
chipbarCoordinator.removeView(routeInfo.id, removalReason)
} else {
+ stateMap[routeInfo.id] = chipState
displayedState = chipState
+ chipbarCoordinator.registerListener(displayListener)
chipbarCoordinator.displayView(
createChipbarInfo(
chipState,
@@ -135,7 +138,7 @@
context,
logger,
)
- ) { stateMap.remove(routeInfo.id) }
+ )
}
}
@@ -182,6 +185,7 @@
}
},
vibrationEffect = chipStateSender.transferStatus.vibrationEffect,
+ allowSwipeToDismiss = true,
windowTitle = MediaTttUtils.WINDOW_TITLE_SENDER,
wakeReason = MediaTttUtils.WAKE_REASON_SENDER,
timeoutMs = chipStateSender.timeout,
@@ -225,4 +229,14 @@
onClickListener,
)
}
+
+ private val displayListener =
+ TemporaryViewDisplayController.Listener { id -> removeIdFromStore(id) }
+
+ private fun removeIdFromStore(id: String) {
+ stateMap.remove(id)
+ if (stateMap.isEmpty()) {
+ chipbarCoordinator.unregisterListener(displayListener)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index a92203c..1121e160 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -297,7 +297,7 @@
private void updateAssistantAvailability() {
boolean assistantAvailableForUser = mAssistManagerLazy.get()
- .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+ .getAssistInfoForUser(mUserTracker.getUserId()) != null;
boolean longPressDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index e0aa6a8..06db5ed 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -77,7 +77,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.telecom.TelecomManager;
import android.text.TextUtils;
@@ -1492,7 +1491,7 @@
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
final String chooserClassName = AccessibilityButtonChooserActivity.class.getName();
intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ mContext.startActivityAsUser(intent, mUserTracker.getUserHandle());
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index e64c188..046a284 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -24,7 +24,6 @@
import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -63,8 +62,8 @@
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -87,6 +86,7 @@
private final Handler mHandler;
private final NavigationBarComponent.Factory mNavigationBarComponentFactory;
private FeatureFlags mFeatureFlags;
+ private final SecureSettings mSecureSettings;
private final DisplayManager mDisplayManager;
private final TaskbarDelegate mTaskbarDelegate;
private int mNavMode;
@@ -118,11 +118,13 @@
TaskStackChangeListeners taskStackChangeListeners,
Optional<Pip> pipOptional,
Optional<BackAnimation> backAnimation,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ SecureSettings secureSettings) {
mContext = context;
mHandler = mainHandler;
mNavigationBarComponentFactory = navigationBarComponentFactory;
mFeatureFlags = featureFlags;
+ mSecureSettings = secureSettings;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
commandQueue.addCallback(this);
configurationController.addCallback(this);
@@ -192,8 +194,7 @@
}
private void updateAccessibilityButtonModeIfNeeded() {
- ContentResolver contentResolver = mContext.getContentResolver();
- final int mode = Settings.Secure.getIntForUser(contentResolver,
+ final int mode = mSecureSettings.getIntForUser(
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, UserHandle.USER_CURRENT);
@@ -207,14 +208,14 @@
// force update to ACCESSIBILITY_BUTTON_MODE_GESTURE.
if (QuickStepContract.isGesturalMode(mNavMode)
&& mode == ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR) {
- Settings.Secure.putIntForUser(contentResolver,
+ mSecureSettings.putIntForUser(
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_GESTURE,
UserHandle.USER_CURRENT);
// ACCESSIBILITY_BUTTON_MODE_GESTURE is incompatible under non gestural mode. Need to
// force update to ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR.
} else if (!QuickStepContract.isGesturalMode(mNavMode)
&& mode == ACCESSIBILITY_BUTTON_MODE_GESTURE) {
- Settings.Secure.putIntForUser(contentResolver,
+ mSecureSettings.putIntForUser(
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, UserHandle.USER_CURRENT);
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
index 26e3f49..4b10d69 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
@@ -72,6 +72,9 @@
companion object {
// TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
+
+ // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
+ const val NOTE_ROLE = "android.app.role.NOTES"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index 8bdf319..22ce121 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -18,11 +18,13 @@
import android.app.Activity
import android.app.KeyguardManager
+import android.app.role.RoleManager
import android.content.Context
import android.os.UserManager
import androidx.core.content.getSystemService
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import dagger.Binds
@@ -33,20 +35,25 @@
import java.util.Optional
/** Compose all dependencies required by Note Task feature. */
-@Module
+@Module(includes = [NoteTaskQuickAffordanceModule::class])
internal interface NoteTaskModule {
@[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
- fun bindNoteTaskLauncherActivity(activity: LaunchNoteTaskActivity): Activity?
+ fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity
@[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)]
- fun bindNoteTaskShortcutActivity(activity: CreateNoteTaskShortcutActivity): Activity?
+ fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity
companion object {
@[Provides NoteTaskEnabledKey]
- fun provideIsNoteTaskEnabled(featureFlags: FeatureFlags): Boolean {
- return featureFlags.isEnabled(Flags.NOTE_TASKS)
+ fun provideIsNoteTaskEnabled(
+ featureFlags: FeatureFlags,
+ roleManager: RoleManager,
+ ): Boolean {
+ val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskIntentResolver.NOTE_ROLE)
+ val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
+ return isRoleAvailable && isFeatureEnabled
}
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
new file mode 100644
index 0000000..cfbaa48
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.notetask.quickaffordance
+
+import android.content.Context
+import com.android.systemui.R
+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.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.PickerScreenState
+import com.android.systemui.notetask.NoteTaskController
+import com.android.systemui.notetask.NoteTaskEnabledKey
+import javax.inject.Inject
+import kotlinx.coroutines.flow.flowOf
+
+internal class NoteTaskQuickAffordanceConfig
+@Inject
+constructor(
+ context: Context,
+ private val noteTaskController: NoteTaskController,
+ @NoteTaskEnabledKey private val isEnabled: Boolean,
+) : KeyguardQuickAffordanceConfig {
+
+ override val key = BuiltInKeyguardQuickAffordanceKeys.CREATE_NOTE
+
+ override val pickerName: String = context.getString(R.string.note_task_button_label)
+
+ override val pickerIconResourceId = R.drawable.ic_note_task_shortcut_keyguard
+
+ override val lockScreenState = flowOf(getLockScreenState())
+
+ // TODO(b/265949213)
+ private fun getLockScreenState() =
+ if (isEnabled) {
+ val icon = Icon.Resource(pickerIconResourceId, ContentDescription.Loaded(pickerName))
+ LockScreenState.Visible(icon)
+ } else {
+ LockScreenState.Hidden
+ }
+
+ override suspend fun getPickerScreenState() =
+ if (isEnabled) {
+ PickerScreenState.Default()
+ } else {
+ PickerScreenState.UnavailableOnDevice
+ }
+
+ override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
+ noteTaskController.showNoteTask()
+ return OnTriggeredResult.Handled
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
new file mode 100644
index 0000000..7cb932a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.notetask.quickaffordance
+
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+
+@Module
+internal interface NoteTaskQuickAffordanceModule {
+
+ @[Binds IntoSet]
+ fun NoteTaskQuickAffordanceConfig.bindNoteTaskQuickAffordance(): KeyguardQuickAffordanceConfig
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index f6a623e..6ab0da6 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -46,7 +46,7 @@
id = SHORTCUT_ID,
shortLabel = getString(R.string.note_task_button_label),
intent = LaunchNoteTaskActivity.newIntent(context = this),
- iconResource = R.drawable.ic_note_task_button,
+ iconResource = R.drawable.ic_note_task_shortcut_widget,
)
setResult(Activity.RESULT_OK, intent)
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 3587c4d..8d8903d 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -68,6 +68,7 @@
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.NotificationChannels;
@@ -177,7 +178,7 @@
private final BroadcastSender mBroadcastSender;
private final UiEventLogger mUiEventLogger;
private GlobalSettings mGlobalSettings;
-
+ private final UserTracker mUserTracker;
private final Lazy<BatteryController> mBatteryControllerLazy;
private final DialogLaunchAnimator mDialogLaunchAnimator;
@@ -187,7 +188,7 @@
public PowerNotificationWarnings(Context context, ActivityStarter activityStarter,
BroadcastSender broadcastSender, Lazy<BatteryController> batteryControllerLazy,
DialogLaunchAnimator dialogLaunchAnimator, UiEventLogger uiEventLogger,
- GlobalSettings globalSettings) {
+ GlobalSettings globalSettings, UserTracker userTracker) {
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -200,6 +201,7 @@
mUseSevereDialog = mContext.getResources().getBoolean(R.bool.config_severe_battery_dialog);
mUiEventLogger = uiEventLogger;
mGlobalSettings = globalSettings;
+ mUserTracker = userTracker;
}
@Override
@@ -699,7 +701,7 @@
Secure.putIntForUser(
resolver,
Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
- 1, UserHandle.USER_CURRENT);
+ 1, mUserTracker.getUserId());
});
} else {
d.setTitle(R.string.battery_saver_confirmation_title);
@@ -850,7 +852,8 @@
logEvent(BatteryWarningEvents
.LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION_SETTINGS);
dismissLowBatteryNotification();
- mContext.startActivityAsUser(mOpenBatterySaverSettings, UserHandle.CURRENT);
+ mContext.startActivityAsUser(mOpenBatterySaverSettings,
+ mUserTracker.getUserHandle());
} else if (action.equals(ACTION_START_SAVER)) {
logEvent(BatteryWarningEvents
.LowBatteryWarningEvent.LOW_BATTERY_NOTIFICATION_TURN_ON);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
index 39d081d..36dc743 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/ReduceBrightColorsController.java
@@ -83,8 +83,7 @@
if (mListeners.size() > 0) {
mSecureSettings.unregisterContentObserver(mContentObserver);
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(
- Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
false, mContentObserver, newUser);
}
}
@@ -100,8 +99,7 @@
mListeners.add(listener);
if (mListeners.size() == 1) {
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(
- Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
false, mContentObserver, mUserTracker.getUserId());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 4d005be..1151475 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -21,7 +21,6 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
-import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
@@ -44,8 +43,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.graphics.Insets;
-import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.input.InputManager;
import android.os.Binder;
@@ -77,6 +74,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.util.ScreenshotRequest;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -94,7 +92,6 @@
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -311,7 +308,7 @@
intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ mContext.startActivityAsUser(intent, mUserTracker.getUserHandle());
});
}
@@ -322,18 +319,8 @@
}
@Override
- public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
- Insets visibleInsets, Task.TaskKey task) {
- mScreenshotHelper.provideScreenshot(
- screenImageBundle,
- locationInScreen,
- visibleInsets,
- task.id,
- task.userId,
- task.sourceComponent,
- SCREENSHOT_OVERVIEW,
- mHandler,
- null);
+ public void takeScreenshot(ScreenshotRequest request) {
+ mScreenshotHelper.takeScreenshot(request, mHandler, null);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 5450db9..d64b33b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -49,6 +49,7 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.screenshot.ScrollCaptureController.LongScreenshot;
+import com.android.systemui.settings.UserTracker;
import com.google.common.util.concurrent.ListenableFuture;
@@ -79,6 +80,7 @@
private final LongScreenshotData mLongScreenshotHolder;
private final ActionIntentExecutor mActionExecutor;
private final FeatureFlags mFeatureFlags;
+ private final UserTracker mUserTracker;
private ImageView mPreview;
private ImageView mTransitionView;
@@ -110,7 +112,7 @@
public LongScreenshotActivity(UiEventLogger uiEventLogger, ImageExporter imageExporter,
@Main Executor mainExecutor, @Background Executor bgExecutor,
LongScreenshotData longScreenshotHolder, ActionIntentExecutor actionExecutor,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags, UserTracker userTracker) {
mUiEventLogger = uiEventLogger;
mUiExecutor = mainExecutor;
mBackgroundExecutor = bgExecutor;
@@ -118,6 +120,7 @@
mLongScreenshotHolder = longScreenshotHolder;
mActionExecutor = actionExecutor;
mFeatureFlags = featureFlags;
+ mUserTracker = userTracker;
}
@@ -375,7 +378,7 @@
Intent sharingChooserIntent = Intent.createChooser(intent, null)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
+ startActivityAsUser(sharingChooserIntent, mUserTracker.getUserHandle());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
index 95cc0dc..f011aab 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
@@ -19,27 +19,26 @@
import android.graphics.Insets
import android.util.Log
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
-import com.android.internal.util.ScreenshotHelper.HardwareBitmapBundler
-import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
+import com.android.internal.util.ScreenshotRequest
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
-import java.util.function.Consumer
-import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
+import java.util.function.Consumer
+import javax.inject.Inject
/**
* Processes a screenshot request sent from {@link ScreenshotHelper}.
*/
@SysUISingleton
class RequestProcessor @Inject constructor(
- private val capture: ImageCapture,
- private val policy: ScreenshotPolicy,
- private val flags: FeatureFlags,
- /** For the Java Async version, to invoke the callback. */
- @Application private val mainScope: CoroutineScope
+ private val capture: ImageCapture,
+ private val policy: ScreenshotPolicy,
+ private val flags: FeatureFlags,
+ /** For the Java Async version, to invoke the callback. */
+ @Application private val mainScope: CoroutineScope
) {
/**
* Inspects the incoming request, returning a potentially modified request depending on policy.
@@ -58,7 +57,7 @@
// regardless of the managed profile status.
if (request.type != TAKE_SCREENSHOT_PROVIDED_IMAGE &&
- flags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)
+ flags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)
) {
val info = policy.findPrimaryContent(policy.getDefaultDisplayId())
@@ -66,17 +65,21 @@
result = if (policy.isManagedProfile(info.user.identifier)) {
val image = capture.captureTask(info.taskId)
- ?: error("Task snapshot returned a null Bitmap!")
+ ?: error("Task snapshot returned a null Bitmap!")
// Provide the task snapshot as the screenshot
- ScreenshotRequest(
- TAKE_SCREENSHOT_PROVIDED_IMAGE, request.source,
- HardwareBitmapBundler.hardwareBitmapToBundle(image),
- info.bounds, Insets.NONE, info.taskId, info.user.identifier, info.component
- )
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, request.source)
+ .setTopComponent(info.component)
+ .setTaskId(info.taskId)
+ .setUserId(info.user.identifier)
+ .setBitmap(image)
+ .setBoundsOnScreen(info.bounds)
+ .setInsets(Insets.NONE)
+ .build()
} else {
// Create a new request of the same type which includes the top component
- ScreenshotRequest(request.type, request.source, info.component)
+ ScreenshotRequest.Builder(request.type, request.source)
+ .setTopComponent(info.component).build()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index b21a485..6d87922 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -416,10 +416,11 @@
}
boolean showFlash = false;
- if (!aspectRatiosMatch(screenshot, visibleInsets, screenshotScreenBounds)) {
+ if (screenshotScreenBounds == null
+ || !aspectRatiosMatch(screenshot, visibleInsets, screenshotScreenBounds)) {
showFlash = true;
visibleInsets = Insets.NONE;
- screenshotScreenBounds.set(0, 0, screenshot.getWidth(), screenshot.getHeight());
+ screenshotScreenBounds = new Rect(0, 0, screenshot.getWidth(), screenshot.getHeight());
}
mCurrentRequestCallback = requestCallback;
saveScreenshot(screenshot, finisher, screenshotScreenBounds, visibleInsets, topComponent,
@@ -553,6 +554,10 @@
Log.d(TAG, "adding OnComputeInternalInsetsListener");
}
mScreenshotView.getViewTreeObserver().addOnComputeInternalInsetsListener(mScreenshotView);
+ if (DEBUG_WINDOW) {
+ Log.d(TAG, "setContentView: " + mScreenshotView);
+ }
+ setContentView(mScreenshotView);
}
/**
@@ -634,6 +639,7 @@
// The window is focusable by default
setWindowFocusable(true);
+ mScreenshotView.requestFocus();
// Wait until this window is attached to request because it is
// the reference used to locate the target window (below).
@@ -691,10 +697,7 @@
mContext.getDrawable(R.drawable.overlay_badge_background), owner));
}
mScreenshotView.setScreenshot(mScreenBitmap, screenInsets);
- if (DEBUG_WINDOW) {
- Log.d(TAG, "setContentView: " + mScreenshotView);
- }
- setContentView(mScreenshotView);
+
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 35e9f3e..7b271a8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -54,7 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
-import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.util.ScreenshotRequest;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.flags.FeatureFlags;
@@ -186,8 +186,7 @@
final Consumer<Uri> onSaved = (uri) -> reportUri(replyTo, uri);
RequestCallback callback = new RequestCallbackImpl(replyTo);
- ScreenshotHelper.ScreenshotRequest request =
- (ScreenshotHelper.ScreenshotRequest) msg.obj;
+ ScreenshotRequest request = (ScreenshotRequest) msg.obj;
handleRequest(request, onSaved, callback);
return true;
@@ -195,7 +194,7 @@
@MainThread
@VisibleForTesting
- void handleRequest(ScreenshotHelper.ScreenshotRequest request, Consumer<Uri> onSaved,
+ void handleRequest(ScreenshotRequest request, Consumer<Uri> onSaved,
RequestCallback callback) {
// If the storage for this user is locked, we have no place to store
// the screenshot, so skip taking it instead of showing a misleading
@@ -226,7 +225,7 @@
(r) -> dispatchToController(r, onSaved, callback));
}
- private void dispatchToController(ScreenshotHelper.ScreenshotRequest request,
+ private void dispatchToController(ScreenshotRequest request,
Consumer<Uri> uriConsumer, RequestCallback callback) {
ComponentName topComponent = request.getTopComponent();
@@ -244,8 +243,7 @@
if (DEBUG_SERVICE) {
Log.d(TAG, "handleMessage: TAKE_SCREENSHOT_PROVIDED_IMAGE");
}
- Bitmap screenshot = ScreenshotHelper.HardwareBitmapBundler.bundleToHardwareBitmap(
- request.getBitmapBundle());
+ Bitmap screenshot = request.getBitmap();
Rect screenBounds = request.getBoundsInScreen();
Insets insets = request.getInsets();
int taskId = request.getTaskId();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 1558ac5..287e810 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -62,12 +62,24 @@
fun removeCallback(callback: Callback)
/**
- * Ćallback for notifying of changes.
+ * Callback for notifying of changes.
*/
interface Callback {
/**
+ * Notifies that the current user is being changed.
+ * Override this method to run things while the screen is frozen for the user switch.
+ * Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
+ * screen further. Please be aware that code executed in this callback will lengthen the
+ * user switch duration.
+ */
+ @JvmDefault
+ fun onUserChanging(newUser: Int, userContext: Context) {}
+
+ /**
* Notifies that the current user has changed.
+ * Override this method to run things after the screen is unfrozen for the user switch.
+ * Please see {@link #onUserChanging} if you need to hide jank.
*/
@JvmDefault
fun onUserChanged(newUser: Int, userContext: Context) {}
@@ -78,4 +90,4 @@
@JvmDefault
fun onProfilesChanged(profiles: List<@JvmSuppressWildcards UserInfo>) {}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 4dbe099..3a5d0a7 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -16,6 +16,8 @@
package com.android.systemui.settings
+import android.app.IActivityManager
+import android.app.UserSwitchObserver
import android.content.BroadcastReceiver
import android.content.ContentResolver
import android.content.Context
@@ -23,6 +25,7 @@
import android.content.IntentFilter
import android.content.pm.UserInfo
import android.os.Handler
+import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
@@ -33,6 +36,7 @@
import com.android.systemui.util.Assert
import java.io.PrintWriter
import java.lang.ref.WeakReference
+import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@@ -55,6 +59,7 @@
open class UserTrackerImpl internal constructor(
private val context: Context,
private val userManager: UserManager,
+ private val iActivityManager: IActivityManager,
private val dumpManager: DumpManager,
private val backgroundHandler: Handler
) : UserTracker, Dumpable, BroadcastReceiver() {
@@ -106,7 +111,6 @@
setUserIdInternal(startingUser)
val filter = IntentFilter().apply {
- addAction(Intent.ACTION_USER_SWITCHED)
addAction(Intent.ACTION_USER_INFO_CHANGED)
// These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
@@ -117,14 +121,13 @@
}
context.registerReceiverForAllUsers(this, filter, null /* permission */, backgroundHandler)
+ registerUserSwitchObserver()
+
dumpManager.registerDumpable(TAG, this)
}
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
- Intent.ACTION_USER_SWITCHED -> {
- handleSwitchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL))
- }
Intent.ACTION_USER_INFO_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
@@ -156,22 +159,43 @@
return ctx to profiles
}
+ private fun registerUserSwitchObserver() {
+ iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() {
+ override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
+ backgroundHandler.run {
+ handleUserSwitching(newUserId)
+ reply?.sendResult(null)
+ }
+ }
+
+ override fun onUserSwitchComplete(newUserId: Int) {
+ backgroundHandler.run {
+ handleUserSwitchComplete(newUserId)
+ }
+ }
+ }, TAG)
+ }
+
@WorkerThread
- protected open fun handleSwitchUser(newUser: Int) {
+ protected open fun handleUserSwitching(newUserId: Int) {
Assert.isNotMainThread()
- if (newUser == UserHandle.USER_NULL) {
- Log.w(TAG, "handleSwitchUser - Couldn't get new id from intent")
- return
- }
+ Log.i(TAG, "Switching to user $newUserId")
- if (newUser == userId) return
- Log.i(TAG, "Switching to user $newUser")
-
- val (ctx, profiles) = setUserIdInternal(newUser)
-
+ setUserIdInternal(newUserId)
notifySubscribers {
- onUserChanged(newUser, ctx)
- onProfilesChanged(profiles)
+ onUserChanging(newUserId, userContext)
+ }.await()
+ }
+
+ @WorkerThread
+ protected open fun handleUserSwitchComplete(newUserId: Int) {
+ Assert.isNotMainThread()
+ Log.i(TAG, "Switched to user $newUserId")
+
+ setUserIdInternal(newUserId)
+ notifySubscribers {
+ onUserChanged(newUserId, userContext)
+ onProfilesChanged(userProfiles)
}
}
@@ -200,17 +224,25 @@
}
}
- private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
+ private inline fun notifySubscribers(
+ crossinline action: UserTracker.Callback.() -> Unit
+ ): CountDownLatch {
val list = synchronized(callbacks) {
callbacks.toList()
}
+ val latch = CountDownLatch(list.size)
+
list.forEach {
if (it.callback.get() != null) {
it.executor.execute {
it.callback.get()?.action()
+ latch.countDown()
}
+ } else {
+ latch.countDown()
}
}
+ return latch
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -257,4 +289,4 @@
fun sameOrEmpty(other: UserTracker.Callback): Boolean {
return callback.get()?.equals(other) ?: true
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 6bd9158..b69786e 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -208,7 +208,7 @@
automatic = Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
- UserHandle.USER_CURRENT);
+ mUserTracker.getUserId());
mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java b/packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java
index 2f62e44..809fa29 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/dagger/MultiUserUtilsModule.java
@@ -17,6 +17,7 @@
package com.android.systemui.settings.dagger;
import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.content.Context;
import android.os.Handler;
import android.os.UserManager;
@@ -57,11 +58,13 @@
static UserTracker provideUserTracker(
Context context,
UserManager userManager,
+ IActivityManager iActivityManager,
DumpManager dumpManager,
@Background Handler handler
) {
int startingUser = ActivityManager.getCurrentUser();
- UserTrackerImpl tracker = new UserTrackerImpl(context, userManager, dumpManager, handler);
+ UserTrackerImpl tracker = new UserTrackerImpl(context, userManager, iActivityManager,
+ dumpManager, handler);
tracker.initialize(startingUser);
return tracker;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
index 5011227..b3d31f2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
@@ -69,7 +69,8 @@
}
return ConstraintsChanges(
qqsConstraintsChanges = change,
- qsConstraintsChanges = change
+ qsConstraintsChanges = change,
+ largeScreenConstraintsChanges = change,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
index e406be1..8867637 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
@@ -113,7 +113,7 @@
QQS_HEADER_CONSTRAINT -> "QQS Header"
QS_HEADER_CONSTRAINT -> "QS Header"
LARGE_SCREEN_HEADER_CONSTRAINT -> "Large Screen Header"
- else -> "Unknown state"
+ else -> "Unknown state $this"
}
}
@@ -296,6 +296,9 @@
override fun onViewAttached() {
privacyIconsController.chipVisibilityListener = chipVisibilityListener
+ updateVisibility()
+ updateTransition()
+
if (header is MotionLayout) {
header.setOnApplyWindowInsetsListener(insetListener)
clock.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
@@ -308,9 +311,6 @@
dumpManager.registerDumpable(this)
configurationController.addCallback(configurationControllerListener)
demoModeController.addCallback(demoModeReceiver)
-
- updateVisibility()
- updateTransition()
}
override fun onViewDetached() {
@@ -436,15 +436,14 @@
header as MotionLayout
if (largeScreenActive) {
logInstantEvent("Large screen constraints set")
- header.setTransition(HEADER_TRANSITION_ID)
- header.transitionToStart()
+ header.setTransition(LARGE_SCREEN_HEADER_TRANSITION_ID)
} else {
logInstantEvent("Small screen constraints set")
header.setTransition(HEADER_TRANSITION_ID)
- header.transitionToStart()
- updatePosition()
- updateScrollY()
}
+ header.jumpToState(header.startState)
+ updatePosition()
+ updateScrollY()
}
private fun updatePosition() {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index fd31e49..b532c13 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -450,6 +450,7 @@
private float mDownY;
private int mDisplayTopInset = 0; // in pixels
private int mDisplayRightInset = 0; // in pixels
+ private int mDisplayLeftInset = 0; // in pixels
private int mLargeScreenShadeHeaderHeight;
private int mSplitShadeNotificationsScrimMarginBottom;
@@ -3011,7 +3012,7 @@
// left bounds can ignore insets, it should always reach the edge of the screen
return 0;
} else {
- return mNotificationStackScrollLayoutController.getLeft();
+ return mNotificationStackScrollLayoutController.getLeft() + mDisplayLeftInset;
}
}
@@ -3019,7 +3020,7 @@
if (mIsFullWidth) {
return mView.getRight() + mDisplayRightInset;
} else {
- return mNotificationStackScrollLayoutController.getRight();
+ return mNotificationStackScrollLayoutController.getRight() + mDisplayLeftInset;
}
}
@@ -3143,8 +3144,8 @@
// Convert global clipping coordinates to local ones,
// relative to NotificationStackScrollLayout
- int nsslLeft = left - mNotificationStackScrollLayoutController.getLeft();
- int nsslRight = right - mNotificationStackScrollLayoutController.getLeft();
+ int nsslLeft = calculateNsslLeft(left);
+ int nsslRight = calculateNsslRight(right);
int nsslTop = getNotificationsClippingTopBounds(top);
int nsslBottom = bottom - mNotificationStackScrollLayoutController.getTop();
int bottomRadius = mSplitShadeEnabled ? radius : 0;
@@ -3153,6 +3154,22 @@
nsslLeft, nsslTop, nsslRight, nsslBottom, topRadius, bottomRadius);
}
+ private int calculateNsslLeft(int nsslLeftAbsolute) {
+ int left = nsslLeftAbsolute - mNotificationStackScrollLayoutController.getLeft();
+ if (mIsFullWidth) {
+ return left;
+ }
+ return left - mDisplayLeftInset;
+ }
+
+ private int calculateNsslRight(int nsslRightAbsolute) {
+ int right = nsslRightAbsolute - mNotificationStackScrollLayoutController.getLeft();
+ if (mIsFullWidth) {
+ return right;
+ }
+ return right - mDisplayLeftInset;
+ }
+
private int getNotificationsClippingTopBounds(int qsTop) {
if (mSplitShadeEnabled && mExpandingFromHeadsUp) {
// in split shade nssl has extra top margin so clipping at top 0 is not enough, we need
@@ -4169,9 +4186,7 @@
}
private void updateStatusBarIcons() {
- boolean showIconsWhenExpanded =
- (isPanelVisibleBecauseOfHeadsUp() || mIsFullWidth)
- && getExpandedHeight() < getOpeningHeight();
+ boolean showIconsWhenExpanded = getExpandedHeight() < getOpeningHeight();
if (showIconsWhenExpanded && isOnKeyguard()) {
showIconsWhenExpanded = false;
}
@@ -4238,7 +4253,7 @@
&& mHeadsUpAppearanceController.shouldBeVisible()) {
return false;
}
- return !mIsFullWidth || !mShowIconsWhenExpanded;
+ return !mShowIconsWhenExpanded;
}
private void onQsPanelScrollChanged(int scrollY) {
@@ -4550,6 +4565,7 @@
ipw.print("mDownY="); ipw.println(mDownY);
ipw.print("mDisplayTopInset="); ipw.println(mDisplayTopInset);
ipw.print("mDisplayRightInset="); ipw.println(mDisplayRightInset);
+ ipw.print("mDisplayLeftInset="); ipw.println(mDisplayLeftInset);
ipw.print("mLargeScreenShadeHeaderHeight="); ipw.println(mLargeScreenShadeHeaderHeight);
ipw.print("mSplitShadeNotificationsScrimMarginBottom=");
ipw.println(mSplitShadeNotificationsScrimMarginBottom);
@@ -5927,6 +5943,7 @@
Insets combinedInsets = insets.getInsetsIgnoringVisibility(insetTypes);
mDisplayTopInset = combinedInsets.top;
mDisplayRightInset = combinedInsets.right;
+ mDisplayLeftInset = combinedInsets.left;
mNavigationBarBottomHeight = insets.getStableInsetBottom();
updateMaxHeadsUpTranslation();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 26f8b62..ab2e692 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -19,6 +19,7 @@
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
@@ -52,13 +53,13 @@
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.dump.DumpsysTableLogger;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -72,10 +73,8 @@
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -89,6 +88,7 @@
Dumpable, ConfigurationListener {
private static final String TAG = "NotificationShadeWindowController";
+ private static final int MAX_STATE_CHANGES_BUFFER_SIZE = 100;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -108,7 +108,7 @@
private boolean mHasTopUi;
private boolean mHasTopUiChanged;
private float mScreenBrightnessDoze;
- private final State mCurrentState = new State();
+ private final NotificationShadeWindowState mCurrentState = new NotificationShadeWindowState();
private OtherwisedCollapsedListener mListener;
private ForcePluginOpenListener mForcePluginOpenListener;
private Consumer<Integer> mScrimsVisibilityListener;
@@ -125,6 +125,9 @@
private int mDeferWindowLayoutParams;
private boolean mLastKeyguardRotationAllowed;
+ private final NotificationShadeWindowState.Buffer mStateBuffer =
+ new NotificationShadeWindowState.Buffer(MAX_STATE_CHANGES_BUFFER_SIZE);
+
@Inject
public NotificationShadeWindowControllerImpl(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters,
@@ -210,8 +213,8 @@
@VisibleForTesting
void onShadeExpansionFullyChanged(Boolean isExpanded) {
- if (mCurrentState.mPanelExpanded != isExpanded) {
- mCurrentState.mPanelExpanded = isExpanded;
+ if (mCurrentState.panelExpanded != isExpanded) {
+ mCurrentState.panelExpanded = isExpanded;
apply(mCurrentState);
}
}
@@ -251,6 +254,7 @@
mLp.setTitle("NotificationShade");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mLp.privateFlags |= PRIVATE_FLAG_OPTIMIZE_MEASURE;
// We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in
// window manager which disables the transient show behavior.
@@ -296,10 +300,10 @@
mNotificationShadeView.setSystemUiVisibility(vis);
}
- private void applyKeyguardFlags(State state) {
- final boolean keyguardOrAod = state.mKeyguardShowing
- || (state.mDozing && mDozeParameters.getAlwaysOn());
- if ((keyguardOrAod && !state.mBackdropShowing && !state.mLightRevealScrimOpaque)
+ private void applyKeyguardFlags(NotificationShadeWindowState state) {
+ final boolean keyguardOrAod = state.keyguardShowing
+ || (state.dozing && mDozeParameters.getAlwaysOn());
+ if ((keyguardOrAod && !state.mediaBackdropShowing && !state.lightRevealScrimOpaque)
|| mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()) {
// Show the wallpaper if we're on keyguard/AOD and the wallpaper is not occluded by a
// solid backdrop. Also, show it if we are currently animating between the
@@ -310,15 +314,15 @@
mLpChanged.flags &= ~LayoutParams.FLAG_SHOW_WALLPAPER;
}
- if (state.mDozing) {
+ if (state.dozing) {
mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
} else {
mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
}
if (mKeyguardPreferredRefreshRate > 0) {
- boolean onKeyguard = state.mStatusBarState == StatusBarState.KEYGUARD
- && !state.mKeyguardFadingAway && !state.mKeyguardGoingAway;
+ boolean onKeyguard = state.statusBarState == StatusBarState.KEYGUARD
+ && !state.keyguardFadingAway && !state.keyguardGoingAway;
if (onKeyguard
&& mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())) {
// both max and min display refresh rate must be set to take effect:
@@ -332,9 +336,9 @@
(long) mKeyguardPreferredRefreshRate);
} else if (mKeyguardMaxRefreshRate > 0) {
boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled()
- && state.mStatusBarState == StatusBarState.KEYGUARD
- && !state.mKeyguardFadingAway && !state.mKeyguardGoingAway;
- if (state.mDozing || bypassOnKeyguard) {
+ && state.statusBarState == StatusBarState.KEYGUARD
+ && !state.keyguardFadingAway && !state.keyguardGoingAway;
+ if (state.dozing || bypassOnKeyguard) {
mLpChanged.preferredMaxDisplayRefreshRate = mKeyguardMaxRefreshRate;
} else {
mLpChanged.preferredMaxDisplayRefreshRate = 0;
@@ -343,7 +347,7 @@
(long) mLpChanged.preferredMaxDisplayRefreshRate);
}
- if (state.mBouncerShowing && !isDebuggable()) {
+ if (state.bouncerShowing && !isDebuggable()) {
mLpChanged.flags |= LayoutParams.FLAG_SECURE;
} else {
mLpChanged.flags &= ~LayoutParams.FLAG_SECURE;
@@ -354,8 +358,8 @@
return Build.IS_DEBUGGABLE;
}
- private void adjustScreenOrientation(State state) {
- if (state.mBouncerShowing || state.isKeyguardShowingAndNotOccluded() || state.mDozing) {
+ private void adjustScreenOrientation(NotificationShadeWindowState state) {
+ if (state.bouncerShowing || state.isKeyguardShowingAndNotOccluded() || state.dozing) {
if (mKeyguardStateController.isKeyguardScreenRotationAllowed()) {
mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
} else {
@@ -366,10 +370,10 @@
}
}
- private void applyFocusableFlag(State state) {
- boolean panelFocusable = state.mNotificationShadeFocusable && state.mPanelExpanded;
- if (state.mBouncerShowing && (state.mKeyguardOccluded || state.mKeyguardNeedsInput)
- || ENABLE_REMOTE_INPUT && state.mRemoteInputActive
+ private void applyFocusableFlag(NotificationShadeWindowState state) {
+ boolean panelFocusable = state.notificationShadeFocusable && state.panelExpanded;
+ 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.
@@ -379,7 +383,7 @@
} else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
// Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input.
- if (state.mKeyguardNeedsInput && state.isKeyguardShowingAndNotOccluded()) {
+ if (state.keyguardNeedsInput && state.isKeyguardShowingAndNotOccluded()) {
mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else {
mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -390,19 +394,19 @@
}
}
- private void applyForceShowNavigationFlag(State state) {
- if (state.mPanelExpanded || state.mBouncerShowing
- || ENABLE_REMOTE_INPUT && state.mRemoteInputActive) {
+ private void applyForceShowNavigationFlag(NotificationShadeWindowState state) {
+ if (state.panelExpanded || state.bouncerShowing
+ || ENABLE_REMOTE_INPUT && state.remoteInputActive) {
mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
} else {
mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
}
}
- private void applyVisibility(State state) {
+ private void applyVisibility(NotificationShadeWindowState state) {
boolean visible = isExpanded(state);
mLogger.logApplyVisibility(visible);
- if (state.mForcePluginOpen) {
+ if (state.forcePluginOpen) {
if (mListener != null) {
mListener.setWouldOtherwiseCollapse(visible);
}
@@ -418,16 +422,16 @@
}
}
- private boolean isExpanded(State state) {
- return !state.mForceCollapsed && (state.isKeyguardShowingAndNotOccluded()
- || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing
- || state.mHeadsUpShowing
- || state.mScrimsVisibility != ScrimController.TRANSPARENT)
- || state.mBackgroundBlurRadius > 0
- || state.mLaunchingActivity;
+ private boolean isExpanded(NotificationShadeWindowState state) {
+ return !state.forceWindowCollapsed && (state.isKeyguardShowingAndNotOccluded()
+ || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
+ || state.headsUpNotificationShowing
+ || state.scrimsVisibility != ScrimController.TRANSPARENT)
+ || state.backgroundBlurRadius > 0
+ || state.launchingActivityFromNotification;
}
- private void applyFitsSystemWindows(State state) {
+ private void applyFitsSystemWindows(NotificationShadeWindowState state) {
boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
if (mNotificationShadeView != null
&& mNotificationShadeView.getFitsSystemWindows() != fitsSystemWindows) {
@@ -436,21 +440,21 @@
}
}
- private void applyUserActivityTimeout(State state) {
+ private void applyUserActivityTimeout(NotificationShadeWindowState state) {
if (state.isKeyguardShowingAndNotOccluded()
- && state.mStatusBarState == StatusBarState.KEYGUARD
- && !state.mQsExpanded) {
- mLpChanged.userActivityTimeout = state.mBouncerShowing
+ && state.statusBarState == StatusBarState.KEYGUARD
+ && !state.qsExpanded) {
+ mLpChanged.userActivityTimeout = state.bouncerShowing
? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout;
} else {
mLpChanged.userActivityTimeout = -1;
}
}
- private void applyInputFeatures(State state) {
+ private void applyInputFeatures(NotificationShadeWindowState state) {
if (state.isKeyguardShowingAndNotOccluded()
- && state.mStatusBarState == StatusBarState.KEYGUARD
- && !state.mQsExpanded && !state.mForceUserActivity) {
+ && state.statusBarState == StatusBarState.KEYGUARD
+ && !state.qsExpanded && !state.forceUserActivity) {
mLpChanged.inputFeatures |=
LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
} else {
@@ -459,7 +463,7 @@
}
}
- private void applyStatusBarColorSpaceAgnosticFlag(State state) {
+ private void applyStatusBarColorSpaceAgnosticFlag(NotificationShadeWindowState state) {
if (!isExpanded(state)) {
mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
} else {
@@ -485,8 +489,8 @@
applyWindowLayoutParams();
}
- private void apply(State state) {
- mLogger.logNewState(state);
+ private void apply(NotificationShadeWindowState state) {
+ logState(state);
applyKeyguardFlags(state);
applyFocusableFlag(state);
applyForceShowNavigationFlag(state);
@@ -515,6 +519,38 @@
notifyStateChangedCallbacks();
}
+ private void logState(NotificationShadeWindowState state) {
+ mStateBuffer.insert(
+ state.keyguardShowing,
+ state.keyguardOccluded,
+ state.keyguardNeedsInput,
+ state.panelVisible,
+ state.panelExpanded,
+ state.notificationShadeFocusable,
+ state.bouncerShowing,
+ state.keyguardFadingAway,
+ state.keyguardGoingAway,
+ state.qsExpanded,
+ state.headsUpNotificationShowing,
+ state.lightRevealScrimOpaque,
+ state.forceWindowCollapsed,
+ state.forceDozeBrightness,
+ state.forceUserActivity,
+ state.launchingActivityFromNotification,
+ state.mediaBackdropShowing,
+ state.wallpaperSupportsAmbientMode,
+ state.windowNotTouchable,
+ state.componentsForcingTopUi,
+ state.forceOpenTokens,
+ state.statusBarState,
+ state.remoteInputActive,
+ state.forcePluginOpen,
+ state.dozing,
+ state.scrimsVisibility,
+ state.backgroundBlurRadius
+ );
+ }
+
@Override
public void notifyStateChangedCallbacks() {
// Copy callbacks to separate ArrayList to avoid concurrent modification
@@ -523,36 +559,36 @@
.filter(Objects::nonNull)
.collect(Collectors.toList());
for (StatusBarWindowCallback cb : activeCallbacks) {
- cb.onStateChanged(mCurrentState.mKeyguardShowing,
- mCurrentState.mKeyguardOccluded,
- mCurrentState.mBouncerShowing,
- mCurrentState.mDozing,
- mCurrentState.mPanelExpanded);
+ cb.onStateChanged(mCurrentState.keyguardShowing,
+ mCurrentState.keyguardOccluded,
+ mCurrentState.bouncerShowing,
+ mCurrentState.dozing,
+ mCurrentState.panelExpanded);
}
}
- private void applyModalFlag(State state) {
- if (state.mHeadsUpShowing) {
+ private void applyModalFlag(NotificationShadeWindowState state) {
+ if (state.headsUpNotificationShowing) {
mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCH_MODAL;
} else {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
}
- private void applyBrightness(State state) {
- if (state.mForceDozeBrightness) {
+ private void applyBrightness(NotificationShadeWindowState state) {
+ if (state.forceDozeBrightness) {
mLpChanged.screenBrightness = mScreenBrightnessDoze;
} else {
mLpChanged.screenBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
}
}
- private void applyHasTopUi(State state) {
- mHasTopUiChanged = !state.mComponentsForcingTopUi.isEmpty() || isExpanded(state);
+ private void applyHasTopUi(NotificationShadeWindowState state) {
+ mHasTopUiChanged = !state.componentsForcingTopUi.isEmpty() || isExpanded(state);
}
- private void applyNotTouchable(State state) {
- if (state.mNotTouchable) {
+ private void applyNotTouchable(NotificationShadeWindowState state) {
+ if (state.windowNotTouchable) {
mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
} else {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -574,88 +610,88 @@
@Override
public void setKeyguardShowing(boolean showing) {
- mCurrentState.mKeyguardShowing = showing;
+ mCurrentState.keyguardShowing = showing;
apply(mCurrentState);
}
@Override
public void setKeyguardOccluded(boolean occluded) {
- mCurrentState.mKeyguardOccluded = occluded;
+ mCurrentState.keyguardOccluded = occluded;
apply(mCurrentState);
}
@Override
public void setKeyguardNeedsInput(boolean needsInput) {
- mCurrentState.mKeyguardNeedsInput = needsInput;
+ mCurrentState.keyguardNeedsInput = needsInput;
apply(mCurrentState);
}
@Override
public void setPanelVisible(boolean visible) {
- if (mCurrentState.mPanelVisible == visible
- && mCurrentState.mNotificationShadeFocusable == visible) {
+ if (mCurrentState.panelVisible == visible
+ && mCurrentState.notificationShadeFocusable == visible) {
return;
}
mLogger.logShadeVisibleAndFocusable(visible);
- mCurrentState.mPanelVisible = visible;
- mCurrentState.mNotificationShadeFocusable = visible;
+ mCurrentState.panelVisible = visible;
+ mCurrentState.notificationShadeFocusable = visible;
apply(mCurrentState);
}
@Override
public void setNotificationShadeFocusable(boolean focusable) {
mLogger.logShadeFocusable(focusable);
- mCurrentState.mNotificationShadeFocusable = focusable;
+ mCurrentState.notificationShadeFocusable = focusable;
apply(mCurrentState);
}
@Override
public void setBouncerShowing(boolean showing) {
- mCurrentState.mBouncerShowing = showing;
+ mCurrentState.bouncerShowing = showing;
apply(mCurrentState);
}
@Override
public void setBackdropShowing(boolean showing) {
- mCurrentState.mBackdropShowing = showing;
+ mCurrentState.mediaBackdropShowing = showing;
apply(mCurrentState);
}
@Override
public void setKeyguardFadingAway(boolean keyguardFadingAway) {
- mCurrentState.mKeyguardFadingAway = keyguardFadingAway;
+ mCurrentState.keyguardFadingAway = keyguardFadingAway;
apply(mCurrentState);
}
private void onQsExpansionChanged(Boolean expanded) {
- mCurrentState.mQsExpanded = expanded;
+ mCurrentState.qsExpanded = expanded;
apply(mCurrentState);
}
@Override
public void setForceUserActivity(boolean forceUserActivity) {
- mCurrentState.mForceUserActivity = forceUserActivity;
+ mCurrentState.forceUserActivity = forceUserActivity;
apply(mCurrentState);
}
@Override
public void setLaunchingActivity(boolean launching) {
- mCurrentState.mLaunchingActivity = launching;
+ mCurrentState.launchingActivityFromNotification = launching;
apply(mCurrentState);
}
@Override
public boolean isLaunchingActivity() {
- return mCurrentState.mLaunchingActivity;
+ return mCurrentState.launchingActivityFromNotification;
}
@Override
public void setScrimsVisibility(int scrimsVisibility) {
- if (scrimsVisibility == mCurrentState.mScrimsVisibility) {
+ if (scrimsVisibility == mCurrentState.scrimsVisibility) {
return;
}
boolean wasExpanded = isExpanded(mCurrentState);
- mCurrentState.mScrimsVisibility = scrimsVisibility;
+ mCurrentState.scrimsVisibility = scrimsVisibility;
if (wasExpanded != isExpanded(mCurrentState)) {
apply(mCurrentState);
}
@@ -669,31 +705,31 @@
*/
@Override
public void setBackgroundBlurRadius(int backgroundBlurRadius) {
- if (mCurrentState.mBackgroundBlurRadius == backgroundBlurRadius) {
+ if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) {
return;
}
- mCurrentState.mBackgroundBlurRadius = backgroundBlurRadius;
+ mCurrentState.backgroundBlurRadius = backgroundBlurRadius;
apply(mCurrentState);
}
@Override
public void setHeadsUpShowing(boolean showing) {
- mCurrentState.mHeadsUpShowing = showing;
+ mCurrentState.headsUpNotificationShowing = showing;
apply(mCurrentState);
}
@Override
public void setLightRevealScrimOpaque(boolean opaque) {
- if (mCurrentState.mLightRevealScrimOpaque == opaque) {
+ if (mCurrentState.lightRevealScrimOpaque == opaque) {
return;
}
- mCurrentState.mLightRevealScrimOpaque = opaque;
+ mCurrentState.lightRevealScrimOpaque = opaque;
apply(mCurrentState);
}
@Override
public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {
- mCurrentState.mWallpaperSupportsAmbientMode = supportsAmbientMode;
+ mCurrentState.wallpaperSupportsAmbientMode = supportsAmbientMode;
apply(mCurrentState);
}
@@ -701,7 +737,7 @@
* @param state The {@link StatusBarStateController} of the status bar.
*/
private void setStatusBarState(int state) {
- mCurrentState.mStatusBarState = state;
+ mCurrentState.statusBarState = state;
apply(mCurrentState);
}
@@ -712,13 +748,13 @@
*/
@Override
public void setForceWindowCollapsed(boolean force) {
- mCurrentState.mForceCollapsed = force;
+ mCurrentState.forceWindowCollapsed = force;
apply(mCurrentState);
}
@Override
public void onRemoteInputActive(boolean remoteInputActive) {
- mCurrentState.mRemoteInputActive = remoteInputActive;
+ mCurrentState.remoteInputActive = remoteInputActive;
apply(mCurrentState);
}
@@ -728,32 +764,32 @@
*/
@Override
public void setForceDozeBrightness(boolean forceDozeBrightness) {
- if (mCurrentState.mForceDozeBrightness == forceDozeBrightness) {
+ if (mCurrentState.forceDozeBrightness == forceDozeBrightness) {
return;
}
- mCurrentState.mForceDozeBrightness = forceDozeBrightness;
+ mCurrentState.forceDozeBrightness = forceDozeBrightness;
apply(mCurrentState);
}
@Override
public void setDozing(boolean dozing) {
- mCurrentState.mDozing = dozing;
+ mCurrentState.dozing = dozing;
apply(mCurrentState);
}
@Override
public void setForcePluginOpen(boolean forceOpen, Object token) {
if (forceOpen) {
- mCurrentState.mForceOpenTokens.add(token);
+ mCurrentState.forceOpenTokens.add(token);
} else {
- mCurrentState.mForceOpenTokens.remove(token);
+ mCurrentState.forceOpenTokens.remove(token);
}
- final boolean previousForceOpenState = mCurrentState.mForcePluginOpen;
- mCurrentState.mForcePluginOpen = !mCurrentState.mForceOpenTokens.isEmpty();
- if (previousForceOpenState != mCurrentState.mForcePluginOpen) {
+ final boolean previousForceOpenState = mCurrentState.forcePluginOpen;
+ mCurrentState.forcePluginOpen = !mCurrentState.forceOpenTokens.isEmpty();
+ if (previousForceOpenState != mCurrentState.forcePluginOpen) {
apply(mCurrentState);
if (mForcePluginOpenListener != null) {
- mForcePluginOpenListener.onChange(mCurrentState.mForcePluginOpen);
+ mForcePluginOpenListener.onChange(mCurrentState.forcePluginOpen);
}
}
}
@@ -763,12 +799,12 @@
*/
@Override
public boolean getForcePluginOpen() {
- return mCurrentState.mForcePluginOpen;
+ return mCurrentState.forcePluginOpen;
}
@Override
public void setNotTouchable(boolean notTouchable) {
- mCurrentState.mNotTouchable = notTouchable;
+ mCurrentState.windowNotTouchable = notTouchable;
apply(mCurrentState);
}
@@ -777,7 +813,7 @@
*/
@Override
public boolean getPanelExpanded() {
- return mCurrentState.mPanelExpanded;
+ return mCurrentState.panelExpanded;
}
@Override
@@ -800,11 +836,16 @@
if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) {
mNotificationShadeView.getViewRootImpl().dump(" ", pw);
}
+ new DumpsysTableLogger(
+ TAG,
+ NotificationShadeWindowState.TABLE_HEADERS,
+ mStateBuffer.toList()
+ ).printTableData(pw);
}
@Override
public boolean isShowingWallpaper() {
- return !mCurrentState.mBackdropShowing;
+ return !mCurrentState.mediaBackdropShowing;
}
@Override
@@ -834,7 +875,7 @@
*/
@Override
public void setKeyguardGoingAway(boolean goingAway) {
- mCurrentState.mKeyguardGoingAway = goingAway;
+ mCurrentState.keyguardGoingAway = goingAway;
apply(mCurrentState);
}
@@ -846,87 +887,13 @@
@Override
public void setRequestTopUi(boolean requestTopUi, String componentTag) {
if (requestTopUi) {
- mCurrentState.mComponentsForcingTopUi.add(componentTag);
+ mCurrentState.componentsForcingTopUi.add(componentTag);
} else {
- mCurrentState.mComponentsForcingTopUi.remove(componentTag);
+ mCurrentState.componentsForcingTopUi.remove(componentTag);
}
apply(mCurrentState);
}
- private static class State {
- boolean mKeyguardShowing;
- boolean mKeyguardOccluded;
- boolean mKeyguardNeedsInput;
- boolean mPanelVisible;
- boolean mPanelExpanded;
- boolean mNotificationShadeFocusable;
- boolean mBouncerShowing;
- boolean mKeyguardFadingAway;
- boolean mKeyguardGoingAway;
- boolean mQsExpanded;
- boolean mHeadsUpShowing;
- boolean mLightRevealScrimOpaque;
- boolean mForceCollapsed;
- boolean mForceDozeBrightness;
- boolean mForceUserActivity;
- boolean mLaunchingActivity;
- boolean mBackdropShowing;
- boolean mWallpaperSupportsAmbientMode;
- boolean mNotTouchable;
- Set<String> mComponentsForcingTopUi = new HashSet<>();
- Set<Object> mForceOpenTokens = new HashSet<>();
-
- /**
- * The status bar state from {@link CentralSurfaces}.
- */
- int mStatusBarState;
-
- boolean mRemoteInputActive;
- boolean mForcePluginOpen;
- boolean mDozing;
- int mScrimsVisibility;
- int mBackgroundBlurRadius;
-
- private boolean isKeyguardShowingAndNotOccluded() {
- return mKeyguardShowing && !mKeyguardOccluded;
- }
-
- @Override
- public String toString() {
- return new StringBuilder()
- .append("State{")
- .append(" mKeyguardShowing=").append(mKeyguardShowing)
- .append(", mKeyguardOccluded=").append(mKeyguardOccluded)
- .append(", mKeyguardNeedsInput=").append(mKeyguardNeedsInput)
- .append(", mPanelVisible=").append(mPanelVisible)
- .append(", mPanelExpanded=").append(mPanelExpanded)
- .append(", mNotificationShadeFocusable=").append(mNotificationShadeFocusable)
- .append(", mBouncerShowing=").append(mBouncerShowing)
- .append(", mKeyguardFadingAway=").append(mKeyguardFadingAway)
- .append(", mKeyguardGoingAway=").append(mKeyguardGoingAway)
- .append(", mQsExpanded=").append(mQsExpanded)
- .append(", mHeadsUpShowing=").append(mHeadsUpShowing)
- .append(", mLightRevealScrimOpaque=").append(mLightRevealScrimOpaque)
- .append(", mForceCollapsed=").append(mForceCollapsed)
- .append(", mForceDozeBrightness=").append(mForceDozeBrightness)
- .append(", mForceUserActivity=").append(mForceUserActivity)
- .append(", mLaunchingActivity=").append(mLaunchingActivity)
- .append(", mBackdropShowing=").append(mBackdropShowing)
- .append(", mWallpaperSupportsAmbientMode=")
- .append(mWallpaperSupportsAmbientMode)
- .append(", mNotTouchable=").append(mNotTouchable)
- .append(", mComponentsForcingTopUi=").append(mComponentsForcingTopUi)
- .append(", mForceOpenTokens=").append(mForceOpenTokens)
- .append(", mStatusBarState=").append(mStatusBarState)
- .append(", mRemoteInputActive=").append(mRemoteInputActive)
- .append(", mForcePluginOpen=").append(mForcePluginOpen)
- .append(", mDozing=").append(mDozing)
- .append(", mScrimsVisibility=").append(mScrimsVisibility)
- .append(", mBackgroundBlurRadius=").append(mBackgroundBlurRadius)
- .append('}').toString();
- }
- }
-
private final StateListener mStateListener = new StateListener() {
@Override
public void onStateChanged(int newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
new file mode 100644
index 0000000..736404aa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import com.android.systemui.dump.DumpsysTableLogger
+import com.android.systemui.dump.Row
+import com.android.systemui.plugins.util.RingBuffer
+import com.android.systemui.shade.NotificationShadeWindowState.Buffer
+import com.android.systemui.statusbar.StatusBarState
+
+/**
+ * Represents state of shade window, used by [NotificationShadeWindowControllerImpl].
+ * Contains nested class [Buffer] for pretty table logging in bug reports.
+ */
+class NotificationShadeWindowState(
+ @JvmField var keyguardShowing: Boolean = false,
+ @JvmField var keyguardOccluded: Boolean = false,
+ @JvmField var keyguardNeedsInput: Boolean = false,
+ @JvmField var panelVisible: Boolean = false,
+ /** shade panel is expanded (expansion fraction > 0) */
+ @JvmField var panelExpanded: Boolean = false,
+ @JvmField var notificationShadeFocusable: Boolean = false,
+ @JvmField var bouncerShowing: Boolean = false,
+ @JvmField var keyguardFadingAway: Boolean = false,
+ @JvmField var keyguardGoingAway: Boolean = false,
+ @JvmField var qsExpanded: Boolean = false,
+ @JvmField var headsUpNotificationShowing: Boolean = false,
+ @JvmField var lightRevealScrimOpaque: Boolean = false,
+ @JvmField var forceWindowCollapsed: Boolean = false,
+ @JvmField var forceDozeBrightness: Boolean = false,
+ // TODO: forceUserActivity seems to be unused, delete?
+ @JvmField var forceUserActivity: Boolean = false,
+ @JvmField var launchingActivityFromNotification: Boolean = false,
+ @JvmField var mediaBackdropShowing: Boolean = false,
+ @JvmField var wallpaperSupportsAmbientMode: Boolean = false,
+ @JvmField var windowNotTouchable: Boolean = false,
+ @JvmField var componentsForcingTopUi: MutableSet<String> = mutableSetOf(),
+ @JvmField var forceOpenTokens: MutableSet<Any> = mutableSetOf(),
+ /** one of [StatusBarState] */
+ @JvmField var statusBarState: Int = 0,
+ @JvmField var remoteInputActive: Boolean = false,
+ @JvmField var forcePluginOpen: Boolean = false,
+ @JvmField var dozing: Boolean = false,
+ @JvmField var scrimsVisibility: Int = 0,
+ @JvmField var backgroundBlurRadius: Int = 0,
+) {
+
+ fun isKeyguardShowingAndNotOccluded(): Boolean {
+ return keyguardShowing && !keyguardOccluded
+ }
+
+ /** List of [String] to be used as a [Row] with [DumpsysTableLogger]. */
+ val asStringList: List<String> by lazy {
+ listOf(
+ keyguardShowing.toString(),
+ keyguardOccluded.toString(),
+ keyguardNeedsInput.toString(),
+ panelVisible.toString(),
+ panelExpanded.toString(),
+ notificationShadeFocusable.toString(),
+ bouncerShowing.toString(),
+ keyguardFadingAway.toString(),
+ keyguardGoingAway.toString(),
+ qsExpanded.toString(),
+ headsUpNotificationShowing.toString(),
+ lightRevealScrimOpaque.toString(),
+ forceWindowCollapsed.toString(),
+ forceDozeBrightness.toString(),
+ forceUserActivity.toString(),
+ launchingActivityFromNotification.toString(),
+ mediaBackdropShowing.toString(),
+ wallpaperSupportsAmbientMode.toString(),
+ windowNotTouchable.toString(),
+ componentsForcingTopUi.toString(),
+ forceOpenTokens.toString(),
+ StatusBarState.toString(statusBarState),
+ remoteInputActive.toString(),
+ forcePluginOpen.toString(),
+ dozing.toString(),
+ scrimsVisibility.toString(),
+ backgroundBlurRadius.toString()
+ )
+ }
+
+ /**
+ * [RingBuffer] to store [NotificationShadeWindowState]. After the buffer is full, it will
+ * recycle old events.
+ */
+ class Buffer(capacity: Int) {
+
+ private val buffer = RingBuffer(capacity) { NotificationShadeWindowState() }
+
+ /** Insert a new element in the buffer. */
+ fun insert(
+ keyguardShowing: Boolean,
+ keyguardOccluded: Boolean,
+ keyguardNeedsInput: Boolean,
+ panelVisible: Boolean,
+ panelExpanded: Boolean,
+ notificationShadeFocusable: Boolean,
+ bouncerShowing: Boolean,
+ keyguardFadingAway: Boolean,
+ keyguardGoingAway: Boolean,
+ qsExpanded: Boolean,
+ headsUpShowing: Boolean,
+ lightRevealScrimOpaque: Boolean,
+ forceCollapsed: Boolean,
+ forceDozeBrightness: Boolean,
+ forceUserActivity: Boolean,
+ launchingActivity: Boolean,
+ backdropShowing: Boolean,
+ wallpaperSupportsAmbientMode: Boolean,
+ notTouchable: Boolean,
+ componentsForcingTopUi: MutableSet<String>,
+ forceOpenTokens: MutableSet<Any>,
+ statusBarState: Int,
+ remoteInputActive: Boolean,
+ forcePluginOpen: Boolean,
+ dozing: Boolean,
+ scrimsVisibility: Int,
+ backgroundBlurRadius: Int,
+ ) {
+ buffer.advance().apply {
+ this.keyguardShowing = keyguardShowing
+ this.keyguardOccluded = keyguardOccluded
+ this.keyguardNeedsInput = keyguardNeedsInput
+ this.panelVisible = panelVisible
+ this.panelExpanded = panelExpanded
+ this.notificationShadeFocusable = notificationShadeFocusable
+ this.bouncerShowing = bouncerShowing
+ this.keyguardFadingAway = keyguardFadingAway
+ this.keyguardGoingAway = keyguardGoingAway
+ this.qsExpanded = qsExpanded
+ this.headsUpNotificationShowing = headsUpShowing
+ this.lightRevealScrimOpaque = lightRevealScrimOpaque
+ this.forceWindowCollapsed = forceCollapsed
+ this.forceDozeBrightness = forceDozeBrightness
+ this.forceUserActivity = forceUserActivity
+ this.launchingActivityFromNotification = launchingActivity
+ this.mediaBackdropShowing = backdropShowing
+ this.wallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode
+ this.windowNotTouchable = notTouchable
+ this.componentsForcingTopUi.clear()
+ this.componentsForcingTopUi.addAll(componentsForcingTopUi)
+ this.forceOpenTokens.clear()
+ this.forceOpenTokens.addAll(forceOpenTokens)
+ this.statusBarState = statusBarState
+ this.remoteInputActive = remoteInputActive
+ this.forcePluginOpen = forcePluginOpen
+ this.dozing = dozing
+ this.scrimsVisibility = scrimsVisibility
+ this.backgroundBlurRadius = backgroundBlurRadius
+ }
+ }
+
+ /**
+ * Returns the content of the buffer (sorted from latest to newest).
+ *
+ * @see [NotificationShadeWindowState.asStringList]
+ */
+ fun toList(): List<Row> {
+ return buffer.asSequence().map { it.asStringList }.toList()
+ }
+ }
+
+ companion object {
+ /** Headers for dumping a table using [DumpsysTableLogger]. */
+ @JvmField
+ val TABLE_HEADERS =
+ listOf(
+ "keyguardShowing",
+ "keyguardOccluded",
+ "keyguardNeedsInput",
+ "panelVisible",
+ "panelExpanded",
+ "notificationShadeFocusable",
+ "bouncerShowing",
+ "keyguardFadingAway",
+ "keyguardGoingAway",
+ "qsExpanded",
+ "headsUpShowing",
+ "lightRevealScrimOpaque",
+ "forceCollapsed",
+ "forceDozeBrightness",
+ "forceUserActivity",
+ "launchingActivity",
+ "backdropShowing",
+ "wallpaperSupportsAmbientMode",
+ "notTouchable",
+ "componentsForcingTopUi",
+ "forceOpenTokens",
+ "statusBarState",
+ "remoteInputActive",
+ "forcePluginOpen",
+ "dozing",
+ "scrimsVisibility",
+ "backgroundBlurRadius"
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
index db70065..b42bdaa 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
@@ -19,7 +19,6 @@
import android.hardware.display.AmbientDisplayConfiguration
import android.os.PowerManager
import android.os.SystemClock
-import android.os.UserHandle
import android.provider.Settings
import android.view.GestureDetector
import android.view.MotionEvent
@@ -29,6 +28,7 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
import com.android.systemui.tuner.TunerService
@@ -54,6 +54,7 @@
private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
private val statusBarStateController: StatusBarStateController,
private val shadeLogger: ShadeLogger,
+ userTracker: UserTracker,
tunerService: TunerService,
dumpManager: DumpManager
) : GestureDetector.SimpleOnGestureListener(), Dumpable {
@@ -65,10 +66,10 @@
when (key) {
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE ->
doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled(
- UserHandle.USER_CURRENT)
+ userTracker.userId)
Settings.Secure.DOZE_TAP_SCREEN_GESTURE ->
singleTapEnabled = ambientDisplayConfiguration.tapGestureEnabled(
- UserHandle.USER_CURRENT)
+ userTracker.userId)
}
}
tunerService.addTunable(tunable,
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
new file mode 100644
index 0000000..ab0d6e3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.smartspace.config
+
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin
+
+class BcSmartspaceConfigProvider(private val featureFlags: FeatureFlags) :
+ BcSmartspaceConfigPlugin {
+ override val isDefaultDateWeatherDisabled: Boolean
+ get() = featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 6e4ed7b0..7556750 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -53,6 +53,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.util.Pair;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
@@ -1270,7 +1271,8 @@
public void showMediaOutputSwitcher(String packageName) {
int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- throw new SecurityException("Call only allowed from system server.");
+ Slog.e(TAG, "Call only allowed from system server.");
+ return;
}
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsModule.java
new file mode 100644
index 0000000..a797d4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsModule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.BroadcastReceiver;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+/**
+ * Module for {@link com.android.systemui.KeyboardShortcutsReceiver}.
+ */
+@Module
+public abstract class KeyboardShortcutsModule {
+
+ /**
+ *
+ */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyboardShortcutsReceiver.class)
+ public abstract BroadcastReceiver bindKeyboardShortcutsReceiver(
+ KeyboardShortcutsReceiver broadcastReceiver);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
index 6115819..5ab3d7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
@@ -17,90 +17,25 @@
package com.android.systemui.statusbar.gesture
import android.content.Context
-import android.view.InputEvent
import android.view.MotionEvent
-import android.view.MotionEvent.ACTION_CANCEL
-import android.view.MotionEvent.ACTION_DOWN
-import android.view.MotionEvent.ACTION_MOVE
-import android.view.MotionEvent.ACTION_UP
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.window.StatusBarWindowController
import javax.inject.Inject
-/**
- * A class to detect when a user swipes away the status bar. To be notified when the swipe away
- * gesture is detected, add a callback via [addOnGestureDetectedCallback].
- */
+/** A class to detect when a user swipes away the status bar. */
@SysUISingleton
-open class SwipeStatusBarAwayGestureHandler @Inject constructor(
+class SwipeStatusBarAwayGestureHandler
+@Inject
+constructor(
context: Context,
+ logger: SwipeUpGestureLogger,
private val statusBarWindowController: StatusBarWindowController,
- private val logger: SwipeStatusBarAwayGestureLogger
-) : GenericGestureDetector(SwipeStatusBarAwayGestureHandler::class.simpleName!!) {
-
- private var startY: Float = 0f
- private var startTime: Long = 0L
- private var monitoringCurrentTouch: Boolean = false
-
- private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize(
- com.android.internal.R.dimen.system_gestures_start_threshold
- )
-
- override fun onInputEvent(ev: InputEvent) {
- if (ev !is MotionEvent) {
- return
- }
-
- when (ev.actionMasked) {
- ACTION_DOWN -> {
- if (
- // Gesture starts just below the status bar
- ev.y >= statusBarWindowController.statusBarHeight
- && ev.y <= 3 * statusBarWindowController.statusBarHeight
- ) {
- logger.logGestureDetectionStarted(ev.y.toInt())
- startY = ev.y
- startTime = ev.eventTime
- monitoringCurrentTouch = true
- } else {
- monitoringCurrentTouch = false
- }
- }
- ACTION_MOVE -> {
- if (!monitoringCurrentTouch) {
- return
- }
- if (
- // Gesture is up
- ev.y < startY
- // Gesture went far enough
- && (startY - ev.y) >= swipeDistanceThreshold
- // Gesture completed quickly enough
- && (ev.eventTime - startTime) < SWIPE_TIMEOUT_MS
- ) {
- monitoringCurrentTouch = false
- logger.logGestureDetected(ev.y.toInt())
- onGestureDetected(ev)
- }
- }
- ACTION_CANCEL, ACTION_UP -> {
- if (monitoringCurrentTouch) {
- logger.logGestureDetectionEndedWithoutTriggering(ev.y.toInt())
- }
- monitoringCurrentTouch = false
- }
- }
- }
-
- override fun startGestureListening() {
- super.startGestureListening()
- logger.logInputListeningStarted()
- }
-
- override fun stopGestureListening() {
- super.stopGestureListening()
- logger.logInputListeningStopped()
+) : SwipeUpGestureHandler(context, logger, loggerTag = LOGGER_TAG) {
+ override fun startOfGestureIsWithinBounds(ev: MotionEvent): Boolean {
+ // Gesture starts just below the status bar
+ return ev.y >= statusBarWindowController.statusBarHeight &&
+ ev.y <= 3 * statusBarWindowController.statusBarHeight
}
}
-private const val SWIPE_TIMEOUT_MS: Long = 500
+private const val LOGGER_TAG = "SwipeStatusBarAway"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
new file mode 100644
index 0000000..5ecc35c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.gesture
+
+import android.content.Context
+import android.view.InputEvent
+import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_CANCEL
+import android.view.MotionEvent.ACTION_DOWN
+import android.view.MotionEvent.ACTION_MOVE
+import android.view.MotionEvent.ACTION_UP
+import com.android.systemui.dagger.SysUISingleton
+
+/**
+ * A class to detect a generic "swipe up" gesture. To be notified when the swipe up gesture is
+ * detected, add a callback via [addOnGestureDetectedCallback].
+ */
+@SysUISingleton
+abstract class SwipeUpGestureHandler(
+ context: Context,
+ private val logger: SwipeUpGestureLogger,
+ private val loggerTag: String,
+) : GenericGestureDetector(SwipeUpGestureHandler::class.simpleName!!) {
+
+ private var startY: Float = 0f
+ private var startTime: Long = 0L
+ private var monitoringCurrentTouch: Boolean = false
+
+ private var swipeDistanceThreshold: Int = context.resources.getDimensionPixelSize(
+ com.android.internal.R.dimen.system_gestures_start_threshold
+ )
+
+ override fun onInputEvent(ev: InputEvent) {
+ if (ev !is MotionEvent) {
+ return
+ }
+
+ when (ev.actionMasked) {
+ ACTION_DOWN -> {
+ if (
+ startOfGestureIsWithinBounds(ev)
+ ) {
+ logger.logGestureDetectionStarted(loggerTag, ev.y.toInt())
+ startY = ev.y
+ startTime = ev.eventTime
+ monitoringCurrentTouch = true
+ } else {
+ monitoringCurrentTouch = false
+ }
+ }
+ ACTION_MOVE -> {
+ if (!monitoringCurrentTouch) {
+ return
+ }
+ if (
+ // Gesture is up
+ ev.y < startY &&
+ // Gesture went far enough
+ (startY - ev.y) >= swipeDistanceThreshold &&
+ // Gesture completed quickly enough
+ (ev.eventTime - startTime) < SWIPE_TIMEOUT_MS
+ ) {
+ monitoringCurrentTouch = false
+ logger.logGestureDetected(loggerTag, ev.y.toInt())
+ onGestureDetected(ev)
+ }
+ }
+ ACTION_CANCEL, ACTION_UP -> {
+ if (monitoringCurrentTouch) {
+ logger.logGestureDetectionEndedWithoutTriggering(loggerTag, ev.y.toInt())
+ }
+ monitoringCurrentTouch = false
+ }
+ }
+ }
+
+ /**
+ * Returns true if the [ACTION_DOWN] event falls within bounds for this specific swipe-up
+ * gesture.
+ *
+ * Implementations must override this method to specify what part(s) of the screen are valid
+ * locations for the swipe up gesture to start at.
+ */
+ abstract fun startOfGestureIsWithinBounds(ev: MotionEvent): Boolean
+
+ override fun startGestureListening() {
+ super.startGestureListening()
+ logger.logInputListeningStarted(loggerTag)
+ }
+
+ override fun stopGestureListening() {
+ super.stopGestureListening()
+ logger.logInputListeningStopped(loggerTag)
+ }
+}
+
+private const val SWIPE_TIMEOUT_MS: Long = 500
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
similarity index 64%
rename from packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
index 9bdff92..9ce6b02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -16,49 +16,49 @@
package com.android.systemui.statusbar.gesture
-import com.android.systemui.log.dagger.SwipeStatusBarAwayLog
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.dagger.SwipeUpLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
-/** Log messages for [SwipeStatusBarAwayGestureHandler]. */
-class SwipeStatusBarAwayGestureLogger @Inject constructor(
- @SwipeStatusBarAwayLog private val buffer: LogBuffer
+/** Log messages for [SwipeUpGestureHandler]. */
+@SysUISingleton
+class SwipeUpGestureLogger @Inject constructor(
+ @SwipeUpLog private val buffer: LogBuffer,
) {
- fun logGestureDetectionStarted(y: Int) {
+ fun logGestureDetectionStarted(tag: String, y: Int) {
buffer.log(
- TAG,
+ tag,
LogLevel.DEBUG,
{ int1 = y },
{ "Beginning gesture detection. y=$int1" }
)
}
- fun logGestureDetectionEndedWithoutTriggering(y: Int) {
+ fun logGestureDetectionEndedWithoutTriggering(tag: String, y: Int) {
buffer.log(
- TAG,
+ tag,
LogLevel.DEBUG,
{ int1 = y },
{ "Gesture finished; no swipe up gesture detected. Final y=$int1" }
)
}
- fun logGestureDetected(y: Int) {
+ fun logGestureDetected(tag: String, y: Int) {
buffer.log(
- TAG,
+ tag,
LogLevel.INFO,
{ int1 = y },
{ "Gesture detected; notifying callbacks. y=$int1" }
)
}
- fun logInputListeningStarted() {
- buffer.log(TAG, LogLevel.VERBOSE, {}, { "Input listening started "})
+ fun logInputListeningStarted(tag: String) {
+ buffer.log(tag, LogLevel.VERBOSE, {}, { "Input listening started "})
}
- fun logInputListeningStopped() {
- buffer.log(TAG, LogLevel.VERBOSE, {}, { "Input listening stopped "})
+ fun logInputListeningStopped(tag: String) {
+ buffer.log(tag, LogLevel.VERBOSE, {}, { "Input listening stopped "})
}
}
-
-private const val TAG = "SwipeStatusBarAwayGestureHandler"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 91d7e13..803c282 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -43,6 +43,7 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
@@ -60,11 +61,11 @@
import java.util.concurrent.Executor
import javax.inject.Inject
-/**
- * Controller for managing the smartspace view on the lockscreen
- */
+/** Controller for managing the smartspace view on the lockscreen */
@SysUISingleton
-class LockscreenSmartspaceController @Inject constructor(
+class LockscreenSmartspaceController
+@Inject
+constructor(
private val context: Context,
private val featureFlags: FeatureFlags,
private val smartspaceManager: SmartspaceManager,
@@ -81,7 +82,8 @@
@Main private val uiExecutor: Executor,
@Background private val bgExecutor: Executor,
@Main private val handler: Handler,
- optionalPlugin: Optional<BcSmartspaceDataPlugin>
+ optionalPlugin: Optional<BcSmartspaceDataPlugin>,
+ optionalConfigPlugin: Optional<BcSmartspaceConfigPlugin>,
) {
companion object {
private const val TAG = "LockscreenSmartspaceController"
@@ -89,6 +91,7 @@
private var session: SmartspaceSession? = null
private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
+ private val configPlugin: BcSmartspaceConfigPlugin? = optionalConfigPlugin.orElse(null)
// Smartspace can be used on multiple displays, such as when the user casts their screen
private var smartspaceViews = mutableSetOf<SmartspaceView>()
@@ -241,6 +244,7 @@
val ssView = plugin.getView(parent)
ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
+ ssView.registerConfigProvider(configPlugin)
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index 05a9a42..635ed7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -25,6 +25,10 @@
val context: Context,
val featureFlags: FeatureFlags
) {
+ init {
+ featureFlags.addListener(Flags.DISABLE_FSI) { event -> event.requestNoRestart() }
+ }
+
fun isDevLoggingEnabled(): Boolean =
featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
@@ -35,6 +39,8 @@
fun fsiOnDNDUpdate(): Boolean = featureFlags.isEnabled(Flags.FSI_ON_DND_UPDATE)
+ fun disableFsi(): Boolean = featureFlags.isEnabled(Flags.DISABLE_FSI)
+
val shouldFilterUnseenNotifsOnKeyguard: Boolean by lazy {
featureFlags.isEnabled(Flags.FILTER_UNSEEN_NOTIFS_ON_KEYGUARD)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index 7136cad..bc881ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -31,6 +31,10 @@
*/
enum FullScreenIntentDecision {
/**
+ * Full screen intents are disabled.
+ */
+ NO_FSI_DISABLED(false),
+ /**
* No full screen intent included, so there is nothing to show.
*/
NO_FULL_SCREEN_INTENT(false),
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 d9dacfd..9bcf92d 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
@@ -28,7 +28,6 @@
import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
@@ -40,6 +39,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -74,6 +74,7 @@
private final NotifPipelineFlags mFlags;
private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
private final UiEventLogger mUiEventLogger;
+ private final UserTracker mUserTracker;
@VisibleForTesting
protected boolean mUseHeadsUp = false;
@@ -114,7 +115,8 @@
@Main Handler mainHandler,
NotifPipelineFlags flags,
KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
- UiEventLogger uiEventLogger) {
+ UiEventLogger uiEventLogger,
+ UserTracker userTracker) {
mContentResolver = contentResolver;
mPowerManager = powerManager;
mDreamManager = dreamManager;
@@ -127,6 +129,7 @@
mFlags = flags;
mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
mUiEventLogger = uiEventLogger;
+ mUserTracker = userTracker;
ContentObserver headsUpObserver = new ContentObserver(mainHandler) {
@Override
public void onChange(boolean selfChange) {
@@ -236,6 +239,9 @@
@Override
public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
+ if (mFlags.disableFsi()) {
+ return FullScreenIntentDecision.NO_FSI_DISABLED;
+ }
if (entry.getSbn().getNotification().fullScreenIntent == null) {
return FullScreenIntentDecision.NO_FULL_SCREEN_INTENT;
}
@@ -325,6 +331,9 @@
final int uid = entry.getSbn().getUid();
final String packageName = entry.getSbn().getPackageName();
switch (decision) {
+ case NO_FSI_DISABLED:
+ mLogger.logNoFullscreen(entry, "Disabled");
+ return;
case NO_FULL_SCREEN_INTENT:
return;
case NO_FSI_SUPPRESSED_BY_DND:
@@ -450,7 +459,7 @@
* @return true if the entry should ambient pulse, false otherwise
*/
private boolean shouldHeadsUpWhenDozing(NotificationEntry entry, boolean log) {
- if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
+ if (!mAmbientDisplayConfiguration.pulseOnNotificationEnabled(mUserTracker.getUserId())) {
if (log) mLogger.logNoPulsingSettingDisabled(entry);
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryDumper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryDumper.kt
index ffd931c..197ae1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryDumper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryDumper.kt
@@ -18,9 +18,12 @@
package com.android.systemui.statusbar.notification.logging
import android.stats.sysui.NotificationEnums
+import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
+import com.android.systemui.dump.DumpsysTableLogger
+import com.android.systemui.dump.Row
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import java.io.PrintWriter
import javax.inject.Inject
@@ -33,6 +36,7 @@
fun init() {
dumpManager.registerNormalDumpable(javaClass.simpleName, this)
+ Log.i("NotificationMemory", "Registered dumpable.")
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
@@ -45,27 +49,36 @@
/** Renders a table of notification object usage into passed [PrintWriter]. */
private fun dumpNotificationObjects(pw: PrintWriter, memoryUse: List<NotificationMemoryUsage>) {
- pw.println("Notification Object Usage")
- pw.println("-----------")
- pw.println(
- "Package".padEnd(35) +
- "\t\tSmall\tLarge\t${"Style".padEnd(15)}\t\tStyle\tBig\tExtend.\tExtras\tCustom"
- )
- pw.println("".padEnd(35) + "\t\tIcon\tIcon\t${"".padEnd(15)}\t\tIcon\tPicture\t \t \tView")
- pw.println()
-
- memoryUse.forEach { use ->
- pw.println(
- use.packageName.padEnd(35) +
- "\t\t" +
- "${use.objectUsage.smallIcon}\t${use.objectUsage.largeIcon}\t" +
- (styleEnumToString(use.objectUsage.style).take(15) ?: "").padEnd(15) +
- "\t\t${use.objectUsage.styleIcon}\t" +
- "${use.objectUsage.bigPicture}\t${use.objectUsage.extender}\t" +
- "${use.objectUsage.extras}\t${use.objectUsage.hasCustomView}\t" +
- use.notificationKey
+ val columns =
+ listOf(
+ "Package",
+ "Small Icon",
+ "Large Icon",
+ "Style",
+ "Style Icon",
+ "Big Picture",
+ "Extender",
+ "Extras",
+ "Custom View",
+ "Key"
)
- }
+ val rows: List<Row> =
+ memoryUse.map {
+ listOf(
+ it.packageName,
+ toKb(it.objectUsage.smallIcon),
+ toKb(it.objectUsage.largeIcon),
+ styleEnumToString(it.objectUsage.style),
+ toKb(it.objectUsage.styleIcon),
+ toKb(it.objectUsage.bigPicture),
+ toKb(it.objectUsage.extender),
+ toKb(it.objectUsage.extras),
+ it.objectUsage.hasCustomView.toString(),
+ // | is a field delimiter in the output format so we need to replace
+ // it to avoid breakage.
+ it.notificationKey.replace('|', '│')
+ )
+ }
// Calculate totals for easily glanceable summary.
data class Totals(
@@ -88,18 +101,23 @@
t
}
- pw.println()
- pw.println("TOTALS")
- pw.println(
- "".padEnd(35) +
- "\t\t" +
- "${toKb(totals.smallIcon)}\t${toKb(totals.largeIcon)}\t" +
- "".padEnd(15) +
- "\t\t${toKb(totals.styleIcon)}\t" +
- "${toKb(totals.bigPicture)}\t${toKb(totals.extender)}\t" +
- toKb(totals.extras)
- )
- pw.println()
+ val totalsRow: List<Row> =
+ listOf(
+ listOf(
+ "TOTALS",
+ toKb(totals.smallIcon),
+ toKb(totals.largeIcon),
+ "",
+ toKb(totals.styleIcon),
+ toKb(totals.bigPicture),
+ toKb(totals.extender),
+ toKb(totals.extras),
+ "",
+ ""
+ )
+ )
+ val tableLogger = DumpsysTableLogger("Notification Object Usage", columns, rows + totalsRow)
+ tableLogger.printTableData(pw)
}
/** Renders a table of notification view usage into passed [PrintWriter] */
@@ -116,40 +134,65 @@
var softwareBitmapsPenalty: Int = 0,
)
- val totals = Totals()
- pw.println("Notification View Usage")
- pw.println("-----------")
- pw.println("View Type".padEnd(24) + "\tSmall\tLarge\tStyle\tCustom\tSoftware")
- pw.println("".padEnd(24) + "\tIcon\tIcon\tUse\tView\tBitmaps")
- pw.println()
- memoryUse
- .filter { it.viewUsage.isNotEmpty() }
- .forEach { use ->
- pw.println(use.packageName + " " + use.notificationKey)
- use.viewUsage.forEach { view ->
- pw.println(
- " ${view.viewType.toString().padEnd(24)}\t${view.smallIcon}" +
- "\t${view.largeIcon}\t${view.style}" +
- "\t${view.customViews}\t${view.softwareBitmapsPenalty}"
- )
-
- if (view.viewType == ViewType.TOTAL) {
- totals.smallIcon += view.smallIcon
- totals.largeIcon += view.largeIcon
- totals.style += view.style
- totals.customViews += view.customViews
- totals.softwareBitmapsPenalty += view.softwareBitmapsPenalty
+ val columns =
+ listOf(
+ "Package",
+ "View Type",
+ "Small Icon",
+ "Large Icon",
+ "Style Use",
+ "Custom View",
+ "Software Bitmaps",
+ "Key"
+ )
+ val rows =
+ memoryUse
+ .filter { it.viewUsage.isNotEmpty() }
+ .flatMap { use ->
+ use.viewUsage.map { view ->
+ listOf(
+ use.packageName,
+ view.viewType.toString(),
+ toKb(view.smallIcon),
+ toKb(view.largeIcon),
+ toKb(view.style),
+ toKb(view.customViews),
+ toKb(view.softwareBitmapsPenalty),
+ // | is a field delimiter in the output format so we need to replace
+ // it to avoid breakage.
+ use.notificationKey.replace('|', '│')
+ )
}
}
+
+ val totals = Totals()
+ memoryUse
+ .filter { it.viewUsage.isNotEmpty() }
+ .map { it.viewUsage.firstOrNull { view -> view.viewType == ViewType.TOTAL } }
+ .filterNotNull()
+ .forEach { view ->
+ totals.smallIcon += view.smallIcon
+ totals.largeIcon += view.largeIcon
+ totals.style += view.style
+ totals.customViews += view.customViews
+ totals.softwareBitmapsPenalty += view.softwareBitmapsPenalty
}
- pw.println()
- pw.println("TOTALS")
- pw.println(
- " ${"".padEnd(24)}\t${toKb(totals.smallIcon)}" +
- "\t${toKb(totals.largeIcon)}\t${toKb(totals.style)}" +
- "\t${toKb(totals.customViews)}\t${toKb(totals.softwareBitmapsPenalty)}"
- )
- pw.println()
+
+ val totalsRow: List<Row> =
+ listOf(
+ listOf(
+ "TOTALS",
+ "",
+ toKb(totals.smallIcon),
+ toKb(totals.largeIcon),
+ toKb(totals.style),
+ toKb(totals.customViews),
+ toKb(totals.softwareBitmapsPenalty),
+ ""
+ )
+ )
+ val tableLogger = DumpsysTableLogger("Notification View Usage", columns, rows + totalsRow)
+ tableLogger.printTableData(pw)
}
private fun styleEnumToString(styleEnum: Int): String =
@@ -168,6 +211,10 @@
}
private fun toKb(bytes: Int): String {
- return (bytes / 1024).toString() + " KB"
+ if (bytes == 0) {
+ return "--"
+ }
+
+ return "%.2f KB".format(bytes / 1024f)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index fbe88df..7addc8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -24,6 +24,7 @@
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.MathUtils;
+import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
@@ -492,12 +493,9 @@
if (animationListener != null) {
mAppearAnimator.addListener(animationListener);
}
- if (delay > 0) {
- // we need to apply the initial state already to avoid drawn frames in the wrong state
- updateAppearAnimationAlpha();
- updateAppearRect();
- mAppearAnimator.setStartDelay(delay);
- }
+ // we need to apply the initial state already to avoid drawn frames in the wrong state
+ updateAppearAnimationAlpha();
+ updateAppearRect();
mAppearAnimator.addListener(new AnimatorListenerAdapter() {
private boolean mWasCancelled;
@@ -528,7 +526,20 @@
mWasCancelled = true;
}
});
- mAppearAnimator.start();
+
+ // Cache the original animator so we can check if the animation should be started in the
+ // Choreographer callback. It's possible that the original animator (mAppearAnimator) is
+ // replaced with a new value before the callback is called.
+ ValueAnimator cachedAnimator = mAppearAnimator;
+ // Even when delay=0, starting the animation on the next frame is necessary to avoid jank.
+ // Not doing so will increase the chances our Animator will be forced to skip a value of
+ // the animation's progression, causing stutter.
+ Choreographer.getInstance().postFrameCallbackDelayed(
+ frameTimeNanos -> {
+ if (mAppearAnimator == cachedAnimator) {
+ mAppearAnimator.start();
+ }
+ }, delay);
}
private int getCujType(boolean isAppearing) {
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 9f50aef..9275e2b 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
@@ -79,6 +79,8 @@
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -177,6 +179,7 @@
private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
private Optional<BubblesManager> mBubblesManagerOptional;
private MetricsLogger mMetricsLogger;
+ private FeatureFlags mFeatureFlags;
private int mIconTransformContentShift;
private int mMaxHeadsUpHeightBeforeN;
private int mMaxHeadsUpHeightBeforeP;
@@ -277,7 +280,7 @@
private boolean mChildIsExpanding;
private boolean mJustClicked;
- private boolean mIconAnimationRunning;
+ private boolean mAnimationRunning;
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
@@ -451,10 +454,26 @@
return mPublicLayout;
}
- public void setIconAnimationRunning(boolean running) {
- for (NotificationContentView l : mLayouts) {
- setIconAnimationRunning(running, l);
+ /**
+ * Sets animations running in the layouts of this row, including public, private, and children.
+ * @param running whether the animations should be started running or stopped.
+ */
+ public void setAnimationRunning(boolean running) {
+ // Sets animations running in the private/public layouts.
+ if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE)) {
+ for (NotificationContentView l : mLayouts) {
+ if (l != null) {
+ l.setContentAnimationRunning(running);
+ setIconAnimationRunning(running, l);
+ }
+ }
+ } else {
+ for (NotificationContentView l : mLayouts) {
+ setIconAnimationRunning(running, l);
+ }
}
+ // For groups summaries with children, we want to set the children containers
+ // animating as well.
if (mIsSummaryWithChildren) {
NotificationViewWrapper viewWrapper = mChildrenContainer.getNotificationViewWrapper();
if (viewWrapper != null) {
@@ -468,12 +487,18 @@
mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i);
- child.setIconAnimationRunning(running);
+ child.setAnimationRunning(running);
}
}
- mIconAnimationRunning = running;
+ mAnimationRunning = running;
}
+ /**
+ * Starts or stops animations of the icons in all potential content views (regardless of
+ * whether they're contracted, expanded, etc).
+ *
+ * @param running whether to start or stop the icon's animation.
+ */
private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
if (layout != null) {
View contractedChild = layout.getContractedChild();
@@ -485,16 +510,29 @@
}
}
+ /**
+ * Starts or stops animations of the icon in the provided view's icon and right icon.
+ *
+ * @param running whether to start or stop the icon's animation.
+ * @param child the view with the icon to start or stop.
+ */
private void setIconAnimationRunningForChild(boolean running, View child) {
if (child != null) {
ImageView icon = child.findViewById(com.android.internal.R.id.icon);
- setIconRunning(icon, running);
+ setImageViewAnimationRunning(icon, running);
ImageView rightIcon = child.findViewById(com.android.internal.R.id.right_icon);
- setIconRunning(rightIcon, running);
+ setImageViewAnimationRunning(rightIcon, running);
}
}
- private void setIconRunning(ImageView imageView, boolean running) {
+ /**
+ * Starts or stops the animation of a provided image view if it's an AnimationDrawable or an
+ * AnimatedVectorDrawable.
+ *
+ * @param imageView the image view on which to start/stop animation.
+ * @param running whether to start or stop the view's animation.
+ */
+ private void setImageViewAnimationRunning(ImageView imageView, boolean running) {
if (imageView != null) {
Drawable drawable = imageView.getDrawable();
if (drawable instanceof AnimationDrawable) {
@@ -561,8 +599,8 @@
mChildrenContainer.recreateNotificationHeader(mExpandClickListener, isConversation());
mChildrenContainer.onNotificationUpdated();
}
- if (mIconAnimationRunning) {
- setIconAnimationRunning(true);
+ if (mAnimationRunning) {
+ setAnimationRunning(true);
}
if (mLastChronometerRunning) {
setChronometerRunning(true);
@@ -1038,7 +1076,7 @@
notifyHeightChanged(false /* needsAnimation */);
}
if (pinned) {
- setIconAnimationRunning(true);
+ setAnimationRunning(true);
mExpandedWhenPinned = false;
} else if (mExpandedWhenPinned) {
setUserExpanded(true);
@@ -1627,6 +1665,11 @@
);
}
+ /**
+ * Constructs an ExpandableNotificationRow.
+ * @param context context passed to image resolver
+ * @param attrs attributes used to initialize parent view
+ */
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
mImageResolver = new NotificationInlineImageResolver(context,
@@ -1662,7 +1705,8 @@
NotificationGutsManager gutsManager,
MetricsLogger metricsLogger,
SmartReplyConstants smartReplyConstants,
- SmartReplyController smartReplyController) {
+ SmartReplyController smartReplyController,
+ FeatureFlags featureFlags) {
mEntry = entry;
mAppName = appName;
if (mMenuRow == null) {
@@ -1697,6 +1741,7 @@
mBubblesManagerOptional = bubblesManagerOptional;
mNotificationGutsManager = gutsManager;
mMetricsLogger = metricsLogger;
+ mFeatureFlags = featureFlags;
}
private void initDimens() {
@@ -3588,11 +3633,13 @@
@VisibleForTesting
protected void setPrivateLayout(NotificationContentView privateLayout) {
mPrivateLayout = privateLayout;
+ mLayouts = new NotificationContentView[]{mPrivateLayout, mPublicLayout};
}
@VisibleForTesting
protected void setPublicLayout(NotificationContentView publicLayout) {
mPublicLayout = publicLayout;
+ mLayouts = new NotificationContentView[]{mPrivateLayout, mPublicLayout};
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index d113860..bb92dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -219,7 +219,8 @@
mNotificationGutsManager,
mMetricsLogger,
mSmartReplyConstants,
- mSmartReplyController
+ mSmartReplyController,
+ mFeatureFlags
);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index 49dc655..21f4cb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -16,15 +16,22 @@
package com.android.systemui.statusbar.notification.row;
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.StringRes;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.view.View;
+import android.widget.TextView;
import androidx.annotation.NonNull;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -41,6 +48,11 @@
private String mManageNotificationText;
private String mManageNotificationHistoryText;
+ // Footer label
+ private TextView mSeenNotifsFooterTextView;
+ private @StringRes int mSeenNotifsFilteredText;
+ private int mUnlockIconSize;
+
public FooterView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -73,10 +85,41 @@
super.onFinishInflate();
mClearAllButton = (FooterViewButton) findSecondaryView();
mManageButton = findViewById(R.id.manage_text);
+ mSeenNotifsFooterTextView = findViewById(R.id.unlock_prompt_footer);
updateResources();
updateText();
}
+ public void setFooterLabelTextAndIcon(@StringRes int text, @DrawableRes int icon) {
+ mSeenNotifsFilteredText = text;
+ if (mSeenNotifsFilteredText != 0) {
+ mSeenNotifsFooterTextView.setText(mSeenNotifsFilteredText);
+ } else {
+ mSeenNotifsFooterTextView.setText(null);
+ }
+ Drawable drawable;
+ if (icon == 0) {
+ drawable = null;
+ } else {
+ drawable = getResources().getDrawable(icon);
+ drawable.setBounds(0, 0, mUnlockIconSize, mUnlockIconSize);
+ }
+ mSeenNotifsFooterTextView.setCompoundDrawablesRelative(drawable, null, null, null);
+ updateFooterVisibilityMode();
+ }
+
+ private void updateFooterVisibilityMode() {
+ if (mSeenNotifsFilteredText != 0) {
+ mManageButton.setVisibility(View.GONE);
+ mClearAllButton.setVisibility(View.GONE);
+ mSeenNotifsFooterTextView.setVisibility(View.VISIBLE);
+ } else {
+ mManageButton.setVisibility(View.VISIBLE);
+ mClearAllButton.setVisibility(View.VISIBLE);
+ mSeenNotifsFooterTextView.setVisibility(View.GONE);
+ }
+ }
+
public void setManageButtonClickListener(OnClickListener listener) {
mManageButton.setOnClickListener(listener);
}
@@ -135,12 +178,19 @@
mClearAllButton.setTextColor(textColor);
mManageButton.setBackground(theme.getDrawable(R.drawable.notif_footer_btn_background));
mManageButton.setTextColor(textColor);
+ final @ColorInt int labelTextColor =
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorPrimary);
+ mSeenNotifsFooterTextView.setTextColor(labelTextColor);
+ mSeenNotifsFooterTextView.setCompoundDrawableTintList(
+ ColorStateList.valueOf(labelTextColor));
}
private void updateResources() {
mManageNotificationText = getContext().getString(R.string.manage_notifications_text);
mManageNotificationHistoryText = getContext()
.getString(R.string.manage_notifications_history_text);
+ mUnlockIconSize = getResources()
+ .getDimensionPixelSize(R.dimen.notifications_unseen_footer_icon_size);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index e46bf52..4a023c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -184,6 +184,8 @@
private boolean mRemoteInputVisible;
private int mUnrestrictedContentHeight;
+ private boolean mContentAnimating;
+
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mHybridGroupManager = new HybridGroupManager(getContext());
@@ -2129,8 +2131,49 @@
return false;
}
+ /**
+ * Starts and stops animations in the underlying views.
+ * Avoids restarting the animations by checking whether they're already running first.
+ * Return value is used for testing.
+ *
+ * @param running whether to start animations running, or stop them.
+ * @return true if the state of animations changed.
+ */
+ public boolean setContentAnimationRunning(boolean running) {
+ boolean stateChangeRequired = (running != mContentAnimating);
+ if (stateChangeRequired) {
+ // Starts or stops the animations in the potential views.
+ if (mContractedWrapper != null) {
+ mContractedWrapper.setAnimationsRunning(running);
+ }
+ if (mExpandedWrapper != null) {
+ mExpandedWrapper.setAnimationsRunning(running);
+ }
+ if (mHeadsUpWrapper != null) {
+ mHeadsUpWrapper.setAnimationsRunning(running);
+ }
+ // Updates the state tracker.
+ mContentAnimating = running;
+ return true;
+ }
+ return false;
+ }
+
private static class RemoteInputViewData {
@Nullable RemoteInputView mView;
@Nullable RemoteInputViewController mController;
}
+
+ @VisibleForTesting
+ protected void setContractedWrapper(NotificationViewWrapper contractedWrapper) {
+ mContractedWrapper = contractedWrapper;
+ }
+ @VisibleForTesting
+ protected void setExpandedWrapper(NotificationViewWrapper expandedWrapper) {
+ mExpandedWrapper = expandedWrapper;
+ }
+ @VisibleForTesting
+ protected void setHeadsUpWrapper(NotificationViewWrapper headsUpWrapper) {
+ mHeadsUpWrapper = headsUpWrapper;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
index 8732696..175ba15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapper.java
@@ -18,11 +18,15 @@
import android.app.Notification;
import android.content.Context;
+import android.graphics.drawable.AnimatedImageDrawable;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.view.View;
+import com.android.internal.R;
+import com.android.internal.widget.BigPictureNotificationImageView;
import com.android.systemui.statusbar.notification.ImageTransformState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -31,6 +35,8 @@
*/
public class NotificationBigPictureTemplateViewWrapper extends NotificationTemplateViewWrapper {
+ private BigPictureNotificationImageView mImageView;
+
protected NotificationBigPictureTemplateViewWrapper(Context ctx, View view,
ExpandableNotificationRow row) {
super(ctx, view, row);
@@ -39,9 +45,14 @@
@Override
public void onContentUpdated(ExpandableNotificationRow row) {
super.onContentUpdated(row);
+ resolveViews();
updateImageTag(row.getEntry().getSbn());
}
+ private void resolveViews() {
+ mImageView = mView.findViewById(R.id.big_picture);
+ }
+
private void updateImageTag(StatusBarNotification sbn) {
final Bundle extras = sbn.getNotification().extras;
Icon bigLargeIcon = extras.getParcelable(Notification.EXTRA_LARGE_ICON_BIG, Icon.class);
@@ -54,4 +65,25 @@
mRightIcon.setTag(ImageTransformState.ICON_TAG, getLargeIcon(sbn.getNotification()));
}
}
+
+ /**
+ * Starts or stops the animations in any drawables contained in this BigPicture Notification.
+ *
+ * @param running Whether the animations should be set to run.
+ */
+ @Override
+ public void setAnimationsRunning(boolean running) {
+ if (mImageView == null) {
+ return;
+ }
+ Drawable d = mImageView.getDrawable();
+ if (d instanceof AnimatedImageDrawable) {
+ AnimatedImageDrawable animatedImageDrawable = (AnimatedImageDrawable) d;
+ if (running) {
+ animatedImageDrawable.start();
+ } else {
+ animatedImageDrawable.stop();
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index e136055..10753f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -17,16 +17,20 @@
package com.android.systemui.statusbar.notification.row.wrapper
import android.content.Context
+import android.graphics.drawable.AnimatedImageDrawable
import android.view.View
import android.view.ViewGroup
import com.android.internal.widget.CachingIconView
import com.android.internal.widget.ConversationLayout
+import com.android.internal.widget.MessagingGroup
+import com.android.internal.widget.MessagingImageMessage
import com.android.internal.widget.MessagingLinearLayout
import com.android.systemui.R
import com.android.systemui.statusbar.notification.NotificationFadeAware
import com.android.systemui.statusbar.notification.NotificationUtils
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.wrapper.NotificationMessagingTemplateViewWrapper.setCustomImageMessageTransform
+import com.android.systemui.util.children
/**
* Wraps a notification containing a conversation template
@@ -49,6 +53,7 @@
private lateinit var expandBtn: View
private lateinit var expandBtnContainer: View
private lateinit var imageMessageContainer: ViewGroup
+ private lateinit var messageContainers: ArrayList<MessagingGroup>
private lateinit var messagingLinearLayout: MessagingLinearLayout
private lateinit var conversationTitleView: View
private lateinit var importanceRing: View
@@ -60,6 +65,7 @@
private fun resolveViews() {
messagingLinearLayout = conversationLayout.messagingLinearLayout
imageMessageContainer = conversationLayout.imageMessageContainer
+ messageContainers = conversationLayout.messagingGroups
with(conversationLayout) {
conversationIconContainer =
requireViewById(com.android.internal.R.id.conversation_icon_container)
@@ -146,4 +152,26 @@
NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded)
NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded)
}
+
+ // Starts or stops the animations in any drawables contained in this Conversation Notification.
+ override fun setAnimationsRunning(running: Boolean) {
+ // We apply to both the child message containers in a conversation group,
+ // and the top level image message container.
+ val containers = messageContainers.asSequence().map { it.messageContainer } +
+ sequenceOf(imageMessageContainer)
+ val drawables =
+ containers
+ .flatMap { it.children }
+ .mapNotNull { child ->
+ (child as? MessagingImageMessage)?.let { imageMessage ->
+ imageMessage.drawable as? AnimatedImageDrawable
+ }
+ }
+ drawables.toSet().forEach {
+ when {
+ running -> it.start()
+ !running -> it.stop()
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
index c587ce0..4592fde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
@@ -17,9 +17,13 @@
package com.android.systemui.statusbar.notification.row.wrapper;
import android.content.Context;
+import android.graphics.drawable.AnimatedImageDrawable;
+import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.widget.MessagingGroup;
+import com.android.internal.widget.MessagingImageMessage;
import com.android.internal.widget.MessagingLayout;
import com.android.internal.widget.MessagingLinearLayout;
import com.android.systemui.R;
@@ -127,4 +131,40 @@
}
return super.getMinLayoutHeight();
}
+
+ /**
+ * Starts or stops the animations in any drawables contained in this Messaging Notification.
+ *
+ * @param running Whether the animations should be set to run.
+ */
+ @Override
+ public void setAnimationsRunning(boolean running) {
+ if (mMessagingLayout == null) {
+ return;
+ }
+
+ for (MessagingGroup group : mMessagingLayout.getMessagingGroups()) {
+ for (int i = 0; i < group.getMessageContainer().getChildCount(); i++) {
+ View view = group.getMessageContainer().getChildAt(i);
+ // We only need to set animations in MessagingImageMessages.
+ if (!(view instanceof MessagingImageMessage)) {
+ continue;
+ }
+ MessagingImageMessage imageMessage =
+ (com.android.internal.widget.MessagingImageMessage) view;
+
+ // If the drawable isn't an AnimatedImageDrawable, we can't set it to animate.
+ Drawable d = imageMessage.getDrawable();
+ if (!(d instanceof AnimatedImageDrawable)) {
+ continue;
+ }
+ AnimatedImageDrawable animatedImageDrawable = (AnimatedImageDrawable) d;
+ if (running) {
+ animatedImageDrawable.start();
+ } else {
+ animatedImageDrawable.stop();
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 1c22f09..ff5b9cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -403,4 +403,12 @@
NotificationFadeAware.setLayerTypeForFaded(getIcon(), faded);
NotificationFadeAware.setLayerTypeForFaded(getExpandButton(), faded);
}
+
+ /**
+ * Starts or stops the animations in any drawables contained in this Notification.
+ *
+ * @param running Whether the animations should be set to run.
+ */
+ public void setAnimationsRunning(boolean running) {
+ }
}
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 356ddfa..aab36da 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
@@ -538,6 +538,7 @@
private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
private final ScreenOffAnimationController mScreenOffAnimationController;
private boolean mShouldUseSplitNotificationShade;
+ private boolean mHasFilteredOutSeenNotifications;
private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener =
new ExpandableView.OnHeightChangedListener() {
@@ -684,6 +685,10 @@
updateFooter();
}
+ void setHasFilteredOutSeenNotifications(boolean hasFilteredOutSeenNotifications) {
+ mHasFilteredOutSeenNotifications = hasFilteredOutSeenNotifications;
+ }
+
@VisibleForTesting
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooter() {
@@ -3132,7 +3137,7 @@
private void updateAnimationState(boolean running, View child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- row.setIconAnimationRunning(running);
+ row.setAnimationRunning(running);
}
}
@@ -4612,13 +4617,12 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void updateEmptyShadeView(
- boolean visible, boolean areNotificationsHiddenInShade, boolean areSeenNotifsFiltered) {
+ void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
if (areNotificationsHiddenInShade) {
updateEmptyShadeView(R.string.dnd_suppressing_shade_text, 0, 0);
- } else if (areSeenNotifsFiltered) {
+ } else if (mHasFilteredOutSeenNotifications) {
updateEmptyShadeView(
R.string.no_unseen_notif_text,
R.string.unlock_to_see_notif_text,
@@ -4657,13 +4661,20 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
- if (mFooterView == null) {
+ if (mFooterView == null || mNotificationStackSizeCalculator == null) {
return;
}
boolean animate = mIsExpanded && mAnimationsEnabled;
mFooterView.setVisible(visible, animate);
mFooterView.setSecondaryVisible(showDismissView, animate);
mFooterView.showHistory(showHistory);
+ if (mHasFilteredOutSeenNotifications) {
+ mFooterView.setFooterLabelTextAndIcon(
+ R.string.unlock_to_see_notif_text,
+ R.drawable.ic_friction_lock_closed);
+ } else {
+ mFooterView.setFooterLabelTextAndIcon(0, 0);
+ }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 5891948..42d122d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -120,6 +120,7 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Compile;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.List;
@@ -189,6 +190,7 @@
private final FeatureFlags mFeatureFlags;
private final boolean mUseRoundnessSourceTypes;
private final NotificationTargetsHelper mNotificationTargetsHelper;
+ private final SecureSettings mSecureSettings;
private View mLongPressedView;
@@ -667,7 +669,8 @@
NotificationStackScrollLogger logger,
NotificationStackSizeCalculator notificationStackSizeCalculator,
FeatureFlags featureFlags,
- NotificationTargetsHelper notificationTargetsHelper) {
+ NotificationTargetsHelper notificationTargetsHelper,
+ SecureSettings secureSettings) {
mStackStateLogger = stackLogger;
mLogger = logger;
mAllowLongPress = allowLongPress;
@@ -709,6 +712,7 @@
mFeatureFlags = featureFlags;
mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
mNotificationTargetsHelper = notificationTargetsHelper;
+ mSecureSettings = secureSettings;
updateResources();
}
@@ -1015,8 +1019,7 @@
Log.wtf(TAG, "isHistoryEnabled failed to initialize its value");
return false;
}
- mHistoryEnabled = historyEnabled = Settings.Secure.getIntForUser(
- mView.getContext().getContentResolver(),
+ mHistoryEnabled = historyEnabled = mSecureSettings.getIntForUser(
Settings.Secure.NOTIFICATION_HISTORY_ENABLED,
0,
UserHandle.USER_CURRENT) == 1;
@@ -1242,11 +1245,7 @@
// For more details, see: b/228790482
&& !isInTransitionToKeyguard();
- mView.updateEmptyShadeView(
- shouldShow,
- mZenModeController.areNotificationsHiddenInShade(),
- mNotifPipelineFlags.getShouldFilterUnseenNotifsOnKeyguard()
- && mSeenNotificationsProvider.getHasFilteredOutSeenNotifications());
+ mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
Trace.endSection();
}
@@ -1942,6 +1941,9 @@
@Override
public void setNotifStats(@NonNull NotifStats notifStats) {
mNotifStats = notifStats;
+ mView.setHasFilteredOutSeenNotifications(
+ mNotifPipelineFlags.getShouldFilterUnseenNotifsOnKeyguard()
+ && mSeenNotificationsProvider.getHasFilteredOutSeenNotifications());
updateFooter();
updateShowEmptyShadeView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 936589c..66632e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -31,7 +31,6 @@
import android.os.Bundle;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -55,6 +54,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -99,6 +99,7 @@
private final Optional<Vibrator> mVibratorOptional;
private final DisableFlagsLogger mDisableFlagsLogger;
private final int mDisplayId;
+ private final UserTracker mUserTracker;
private final boolean mVibrateOnOpening;
private final VibrationEffect mCameraLaunchGestureVibrationEffect;
private final SystemBarAttributesListener mSystemBarAttributesListener;
@@ -133,7 +134,8 @@
DisableFlagsLogger disableFlagsLogger,
@DisplayId int displayId,
SystemBarAttributesListener systemBarAttributesListener,
- Lazy<CameraLauncher> cameraLauncherLazy) {
+ Lazy<CameraLauncher> cameraLauncherLazy,
+ UserTracker userTracker) {
mCentralSurfaces = centralSurfaces;
mContext = context;
mShadeController = shadeController;
@@ -157,6 +159,7 @@
mDisableFlagsLogger = disableFlagsLogger;
mDisplayId = displayId;
mCameraLauncherLazy = cameraLauncherLazy;
+ mUserTracker = userTracker;
mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation);
mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
@@ -375,7 +378,7 @@
mCentralSurfaces.startActivityDismissingKeyguard(cameraIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
- null /* animationController */, UserHandle.CURRENT);
+ null /* animationController */, mUserTracker.getUserHandle());
} else {
if (!mCentralSurfaces.isDeviceInteractive()) {
// Avoid flickering of the scrim when we instant launch the camera and the bouncer
@@ -432,7 +435,7 @@
mCentralSurfaces.startActivityDismissingKeyguard(emergencyIntent,
false /* onlyProvisioned */, true /* dismissShade */,
true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
- null /* animationController */, UserHandle.CURRENT);
+ null /* animationController */, mUserTracker.getUserHandle());
return;
}
@@ -447,7 +450,7 @@
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.reset(true /* hide */);
}
- mContext.startActivityAsUser(emergencyIntent, UserHandle.CURRENT);
+ mContext.startActivityAsUser(emergencyIntent, mUserTracker.getUserHandle());
return;
}
// We need to defer the emergency action launch until the screen comes on, since otherwise
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 ec08bd4..194d1a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -178,6 +178,7 @@
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.scrim.ScrimView;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelViewController;
@@ -507,6 +508,7 @@
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
private final MessageRouter mMessageRouter;
private final WallpaperManager mWallpaperManager;
+ private final UserTracker mUserTracker;
private CentralSurfacesComponent mCentralSurfacesComponent;
@@ -750,7 +752,8 @@
IDreamManager dreamManager,
Lazy<CameraLauncher> cameraLauncherLazy,
Lazy<LightRevealScrimViewModel> lightRevealScrimViewModelLazy,
- AlternateBouncerInteractor alternateBouncerInteractor
+ AlternateBouncerInteractor alternateBouncerInteractor,
+ UserTracker userTracker
) {
mContext = context;
mNotificationsController = notificationsController;
@@ -830,6 +833,7 @@
mJankMonitor = jankMonitor;
mCameraLauncherLazy = cameraLauncherLazy;
mAlternateBouncerInteractor = alternateBouncerInteractor;
+ mUserTracker = userTracker;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
@@ -867,6 +871,11 @@
wiredChargingRippleController.registerCallbacks();
mLightRevealScrimViewModelLazy = lightRevealScrimViewModelLazy;
+
+ // Based on teamfood flag, turn predictive back dispatch on at runtime.
+ if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
+ mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
+ }
}
@Override
@@ -981,11 +990,6 @@
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy.init();
- // Based on teamfood flag, turn predictive back dispatch on at runtime.
- if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
- mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
- }
-
mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onUnlockedChanged() {
@@ -1397,6 +1401,7 @@
// Things that mean we're not swiping to dismiss the keyguard, and should ignore this
// expansion:
// - Keyguard isn't even visible.
+ // - We're swiping on the bouncer, not the lockscreen.
// - Keyguard is occluded. Expansion changes here are the shade being expanded over the
// occluding activity.
// - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt).
@@ -1406,6 +1411,7 @@
// - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the
// keyguard.
if (!isKeyguardShowing()
+ || mStatusBarKeyguardViewManager.primaryBouncerIsOrWillBeShowing()
|| isOccluded()
|| !mKeyguardStateController.canDismissLockScreen()
|| mKeyguardViewMediator.isAnySimPinSecure()
@@ -4153,7 +4159,8 @@
Log.wtf(TAG, "WallpaperManager not supported");
return;
}
- WallpaperInfo info = mWallpaperManager.getWallpaperInfoForUser(UserHandle.USER_CURRENT);
+ WallpaperInfo info = mWallpaperManager.getWallpaperInfoForUser(
+ mUserTracker.getUserId());
mWallpaperController.onWallpaperInfoUpdated(info);
final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
@@ -4377,6 +4384,6 @@
return new UserHandle(UserHandle.myUserId());
}
}
- return UserHandle.CURRENT;
+ return mUserTracker.getUserHandle();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 0446cef..c248a50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -45,6 +45,7 @@
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -84,6 +85,7 @@
private final ScreenOffAnimationController mScreenOffAnimationController;
private final FoldAodAnimationController mFoldAodAnimationController;
private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+ private final UserTracker mUserTracker;
private final Set<Callback> mCallbacks = new HashSet<>();
@@ -128,7 +130,8 @@
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
ConfigurationController configurationController,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController,
+ UserTracker userTracker) {
mResources = resources;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mAlwaysOnPolicy = alwaysOnDisplayPolicy;
@@ -140,6 +143,7 @@
mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
mScreenOffAnimationController = screenOffAnimationController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mUserTracker = userTracker;
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
tunerService.addTunable(
@@ -169,7 +173,7 @@
private void updateQuickPickupEnabled() {
mIsQuickPickupEnabled =
- mAmbientDisplayConfiguration.quickPickupSensorEnabled(UserHandle.USER_CURRENT);
+ mAmbientDisplayConfiguration.quickPickupSensorEnabled(mUserTracker.getUserId());
}
public boolean getDisplayStateSupported() {
@@ -418,7 +422,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
- mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(mUserTracker.getUserId());
if (key.equals(Settings.Secure.DOZE_ALWAYS_ON)) {
updateControlScreenOff();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index d318759..6873de7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -26,8 +26,6 @@
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.Trace;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -177,11 +175,6 @@
*/
public void show(boolean resetSecuritySelection, boolean isScrimmed) {
final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
- if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
- // In split system user mode, we never unlock system user.
- return;
- }
-
try {
Trace.beginSection("KeyguardBouncer#show");
@@ -212,9 +205,7 @@
}
final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
- final boolean isSystemUser =
- UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
- final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
+ final boolean allowDismissKeyguard = activeUserId == keyguardUserId;
// If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern)
// is set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index 4ad3199..cba0897 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -357,7 +357,7 @@
mView.setOnApplyWindowInsetsListener(
(view, windowInsets) -> mView.updateWindowInsets(windowInsets, mInsetsProvider));
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON),
+ Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
false,
mVolumeSettingObserver,
UserHandle.USER_ALL);
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 48e58fc..6c532a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -35,7 +35,6 @@
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
@@ -58,6 +57,7 @@
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
@@ -136,6 +136,7 @@
private final UserInfoController mUserInfoController;
private final IActivityManager mIActivityManager;
private final UserManager mUserManager;
+ private final UserTracker mUserTracker;
private final DevicePolicyManager mDevicePolicyManager;
private final StatusBarIconController mIconController;
private final CommandQueue mCommandQueue;
@@ -176,7 +177,7 @@
KeyguardStateController keyguardStateController,
LocationController locationController,
SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
- AlarmManager alarmManager, UserManager userManager,
+ AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
DevicePolicyManager devicePolicyManager, RecordingController recordingController,
@Nullable TelecomManager telecomManager, @DisplayId int displayId,
@Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -196,6 +197,7 @@
mUserInfoController = userInfoController;
mIActivityManager = iActivityManager;
mUserManager = userManager;
+ mUserTracker = userTracker;
mDevicePolicyManager = devicePolicyManager;
mRotationLockController = rotationLockController;
mDataSaver = dataSaverController;
@@ -366,7 +368,7 @@
}
private void updateAlarm() {
- final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
+ final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(mUserTracker.getUserId());
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
int zen = mZenController.getZen();
final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index f784723..80093a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -791,20 +791,28 @@
if (!mScreenOffAnimationController.shouldExpandNotifications()
&& !mAnimatingPanelExpansionOnUnlock
&& !occluding) {
- float behindFraction = getInterpolatedFraction();
- behindFraction = (float) Math.pow(behindFraction, 0.8f);
if (mClipsQsScrim) {
+ float behindFraction = getInterpolatedFraction();
+ behindFraction = (float) Math.pow(behindFraction, 0.8f);
mBehindAlpha = mTransparentScrimBackground ? 0 : 1;
mNotificationsAlpha =
mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
} else {
- mBehindAlpha =
- mTransparentScrimBackground ? 0 : behindFraction * mDefaultScrimAlpha;
- // Delay fade-in of notification scrim a bit further, to coincide with the
- // view fade in. Otherwise the empty panel can be quite jarring.
- mNotificationsAlpha = mTransparentScrimBackground
- ? 0 : MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f,
- mPanelExpansionFraction);
+ if (mTransparentScrimBackground) {
+ mBehindAlpha = 0;
+ mNotificationsAlpha = 0;
+ } else {
+ // Behind scrim will finish fading in at 30% expansion.
+ float behindFraction = MathUtils
+ .constrainedMap(0f, 1f, 0f, 0.3f, mPanelExpansionFraction);
+ mBehindAlpha = behindFraction * mDefaultScrimAlpha;
+ // Delay fade-in of notification scrim a bit further, to coincide with the
+ // behind scrim finishing fading in.
+ // Also to coincide with the view starting to fade in, otherwise the empty
+ // panel can be quite jarring.
+ mNotificationsAlpha = MathUtils
+ .constrainedMap(0f, 1f, 0.3f, 0.75f, mPanelExpansionFraction);
+ }
}
mBehindTint = mState.getBehindTint();
mInFrontAlpha = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index be6e0cc..078a00d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -53,6 +53,7 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.NotificationClickNotifier;
@@ -118,6 +119,7 @@
private final NotificationPanelViewController mNotificationPanel;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
private final NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
+ private final UserTracker mUserTracker;
private final OnUserInteractionCallback mOnUserInteractionCallback;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -153,7 +155,8 @@
ActivityLaunchAnimator activityLaunchAnimator,
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider,
LaunchFullScreenIntentProvider launchFullScreenIntentProvider,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ UserTracker userTracker) {
mContext = context;
mMainThreadHandler = mainThreadHandler;
mUiBgExecutor = uiBgExecutor;
@@ -184,6 +187,7 @@
mNotificationPanel = panel;
mActivityLaunchAnimator = activityLaunchAnimator;
mNotificationAnimationProvider = notificationAnimationProvider;
+ mUserTracker = userTracker;
launchFullScreenIntentProvider.registerListener(entry -> launchFullScreenIntent(entry));
}
@@ -518,7 +522,7 @@
intent.getPackage(),
(adapter) -> tsb.startActivities(
getActivityOptions(mCentralSurfaces.getDisplayId(), adapter),
- UserHandle.CURRENT));
+ mUserTracker.getUserHandle()));
});
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index f09c79b..cbd27cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -304,7 +304,7 @@
mAnimationScheduler.addCallback(this);
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON),
+ Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
false,
mVolumeSettingObserver,
UserHandle.USER_ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
index 97b4c2c..e0d156a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepository.kt
@@ -18,6 +18,7 @@
import android.provider.Settings
import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.MobileMappings
import com.android.settingslib.mobile.MobileMappings.Config
@@ -37,6 +38,15 @@
/** Observable for the subscriptionId of the current mobile data connection */
val activeMobileDataSubscriptionId: StateFlow<Int>
+ /**
+ * Observable event for when the active data sim switches but the group stays the same. E.g.,
+ * CBRS switching would trigger this
+ */
+ val activeSubChangedInGroupEvent: Flow<Unit>
+
+ /** Tracks [SubscriptionManager.getDefaultDataSubscriptionId] */
+ val defaultDataSubId: StateFlow<Int>
+
/** The current connectivity status for the default mobile network connection */
val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
index 0c8593d6..b939856 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
@@ -124,6 +124,9 @@
realRepository.activeMobileDataSubscriptionId.value
)
+ override val activeSubChangedInGroupEvent: Flow<Unit> =
+ activeRepo.flatMapLatest { it.activeSubChangedInGroupEvent }
+
override val defaultDataSubRatConfig: StateFlow<MobileMappings.Config> =
activeRepo
.flatMapLatest { it.defaultDataSubRatConfig }
@@ -139,6 +142,11 @@
override val defaultMobileIconGroup: Flow<SignalIcon.MobileIconGroup> =
activeRepo.flatMapLatest { it.defaultMobileIconGroup }
+ override val defaultDataSubId: StateFlow<Int> =
+ activeRepo
+ .flatMapLatest { it.defaultDataSubId }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.defaultDataSubId.value)
+
override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
activeRepo
.flatMapLatest { it.defaultMobileNetworkConnectivity }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index 22aca0a..1088345 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -48,6 +48,7 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -120,6 +121,9 @@
subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
)
+ // TODO(b/261029387): consider adding a demo command for this
+ override val activeSubChangedInGroupEvent: Flow<Unit> = flowOf()
+
/** Demo mode doesn't currently support modifications to the mobile mappings */
override val defaultDataSubRatConfig =
MutableStateFlow(MobileMappings.Config.readConfig(context))
@@ -148,8 +152,12 @@
private fun <K, V> Map<K, V>.reverse() = entries.associateBy({ it.value }) { it.key }
+ // TODO(b/261029387): add a command for this value
+ override val defaultDataSubId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
+
// TODO(b/261029387): not yet supported
- override val defaultMobileNetworkConnectivity = MutableStateFlow(MobileConnectivityModel())
+ override val defaultMobileNetworkConnectivity =
+ MutableStateFlow(MobileConnectivityModel(isConnected = true, isValidated = true))
override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
val current = connectionRepoCache[subId]?.repo
@@ -229,6 +237,9 @@
val connection = getRepoForSubId(subId)
connectionRepoCache[subId]?.lastMobileState = state
+ // TODO(b/261029387): until we have a command, use the most recent subId
+ defaultDataSubId.value = subId
+
// This is always true here, because we split out disabled states at the data-source level
connection.dataEnabled.value = true
connection.networkName.value = NetworkNameModel.Derived(state.name)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index 4472e09..510482d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -35,6 +35,7 @@
import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener
import android.telephony.TelephonyManager
import androidx.annotation.VisibleForTesting
+import com.android.internal.telephony.PhoneConstants
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.MobileMappings.Config
import com.android.systemui.R
@@ -52,6 +53,7 @@
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
+import com.android.systemui.util.kotlin.pairwiseBy
import com.android.systemui.util.settings.GlobalSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -60,9 +62,12 @@
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge
@@ -159,10 +164,24 @@
.logInputChange(logger, "onActiveDataSubscriptionIdChanged")
.stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)
- private val defaultDataSubIdChangedEvent =
+ private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
+ MutableSharedFlow(extraBufferCapacity = 1)
+
+ override val defaultDataSubId: StateFlow<Int> =
broadcastDispatcher
- .broadcastFlow(IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED))
+ .broadcastFlow(
+ IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
+ ) { intent, _ ->
+ intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
+ }
+ .distinctUntilChanged()
.logInputChange(logger, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED")
+ .onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ SubscriptionManager.getDefaultDataSubscriptionId()
+ )
private val carrierConfigChangedEvent =
broadcastDispatcher
@@ -170,7 +189,7 @@
.logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED")
override val defaultDataSubRatConfig: StateFlow<Config> =
- merge(defaultDataSubIdChangedEvent, carrierConfigChangedEvent)
+ merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
.mapLatest { Config.readConfig(context) }
.distinctUntilChanged()
.logInputChange(logger, "defaultDataSubRatConfig")
@@ -258,6 +277,35 @@
.logInputChange(logger, "defaultMobileNetworkConnectivity")
.stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())
+ /**
+ * Flow that tracks the active mobile data subscriptions. Emits `true` whenever the active data
+ * subscription Id changes but the subscription group remains the same. In these cases, we want
+ * to retain the previous subscription's validation status for up to 2s to avoid flickering the
+ * icon.
+ *
+ * TODO(b/265164432): we should probably expose all change events, not just same group
+ */
+ @SuppressLint("MissingPermission")
+ override val activeSubChangedInGroupEvent =
+ flow {
+ activeMobileDataSubscriptionId.pairwiseBy { prevVal: Int, newVal: Int ->
+ if (!defaultMobileNetworkConnectivity.value.isValidated) {
+ return@pairwiseBy
+ }
+ val prevSub = subscriptionManager.getActiveSubscriptionInfo(prevVal)
+ val nextSub = subscriptionManager.getActiveSubscriptionInfo(newVal)
+
+ if (prevSub == null || nextSub == null) {
+ return@pairwiseBy
+ }
+
+ if (prevSub.groupUuid != null && prevSub.groupUuid == nextSub.groupUuid) {
+ emit(Unit)
+ }
+ }
+ }
+ .flowOn(bgDispatcher)
+
private fun isValidSubId(subId: Int): Boolean {
subscriptions.value.forEach {
if (it.subscriptionId == subId) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 003df24..9cdff96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -18,9 +18,11 @@
import android.telephony.CarrierConfigManager
import com.android.settingslib.SignalIcon.MobileIconGroup
+import com.android.settingslib.mobile.TelephonyIcons.NOT_DEFAULT_DATA
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
@@ -41,12 +43,29 @@
/** The current mobile data activity */
val activity: Flow<DataActivityModel>
+ /**
+ * This bit is meant to be `true` if and only if the default network capabilities (see
+ * [android.net.ConnectivityManager.registerDefaultNetworkCallback]) result in a network that
+ * has the [android.net.NetworkCapabilities.TRANSPORT_CELLULAR] represented.
+ *
+ * Note that this differs from [isDataConnected], which is tracked by telephony and has to do
+ * with the state of using this mobile connection for data as opposed to just voice. It is
+ * possible for a mobile subscription to be connected but not be in a connected data state, and
+ * thus we wouldn't want to show the network type icon.
+ */
+ val isConnected: Flow<Boolean>
+
+ /**
+ * True when telephony tells us that the data state is CONNECTED. See
+ * [android.telephony.TelephonyCallback.DataConnectionStateListener] for more details. We
+ * consider this connection to be serving data, and thus want to show a network type icon, when
+ * data is connected. Other data connection states would typically cause us not to show the icon
+ */
+ val isDataConnected: StateFlow<Boolean>
+
/** Only true if mobile is the default transport but is not validated, otherwise false */
val isDefaultConnectionFailed: StateFlow<Boolean>
- /** True when telephony tells us that the data state is CONNECTED */
- val isDataConnected: StateFlow<Boolean>
-
/** True if we consider this connection to be in service, i.e. can make calls */
val isInService: StateFlow<Boolean>
@@ -100,8 +119,10 @@
defaultSubscriptionHasDataEnabled: StateFlow<Boolean>,
override val alwaysShowDataRatIcon: StateFlow<Boolean>,
override val alwaysUseCdmaLevel: StateFlow<Boolean>,
+ defaultMobileConnectivity: StateFlow<MobileConnectivityModel>,
defaultMobileIconMapping: StateFlow<Map<String, MobileIconGroup>>,
defaultMobileIconGroup: StateFlow<MobileIconGroup>,
+ defaultDataSubId: StateFlow<Int>,
override val isDefaultConnectionFailed: StateFlow<Boolean>,
connectionRepository: MobileConnectionRepository,
) : MobileIconInteractor {
@@ -111,8 +132,19 @@
override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
+ override val isConnected: Flow<Boolean> = defaultMobileConnectivity.mapLatest { it.isConnected }
+
override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled
+ private val isDefault =
+ defaultDataSubId
+ .mapLatest { connectionRepository.subId == it }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ connectionRepository.subId == defaultDataSubId.value
+ )
+
override val isDefaultDataEnabled = defaultSubscriptionHasDataEnabled
override val networkName =
@@ -137,7 +169,12 @@
connectionInfo,
defaultMobileIconMapping,
defaultMobileIconGroup,
- ) { info, mapping, defaultGroup ->
+ isDefault,
+ ) { info, mapping, defaultGroup, isDefault ->
+ if (!isDefault) {
+ return@combine NOT_DEFAULT_DATA
+ }
+
when (info.resolvedNetworkType) {
is ResolvedNetworkType.CarrierMergedNetworkType ->
info.resolvedNetworkType.iconGroupOverride
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index 83da1dd..9ae38e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -23,6 +23,7 @@
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
@@ -31,14 +32,17 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
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.mapLatest
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transformLatest
/**
* Business layer logic for the set of mobile subscription icons.
@@ -62,6 +66,17 @@
/** True if the CDMA level should be preferred over the primary level. */
val alwaysUseCdmaLevel: StateFlow<Boolean>
+ /** Tracks the subscriptionId set as the default for data connections */
+ val defaultDataSubId: StateFlow<Int>
+
+ /**
+ * The connectivity of the default mobile network. Note that this can differ from what is
+ * reported from [MobileConnectionsRepository] in some cases. E.g., when the active subscription
+ * changes but the groupUuid remains the same, we keep the old validation information for 2
+ * seconds to avoid icon flickering.
+ */
+ val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel>
+
/** The icon mapping from network type to [MobileIconGroup] for the default subscription */
val defaultMobileIconMapping: StateFlow<Map<String, MobileIconGroup>>
/** Fallback [MobileIconGroup] in the case where there is no icon in the mapping */
@@ -154,6 +169,48 @@
}
}
+ override val defaultDataSubId = mobileConnectionsRepo.defaultDataSubId
+
+ /**
+ * Copied from the old pipeline. We maintain a 2s period of time where we will keep the
+ * validated bit from the old active network (A) while data is changing to the new one (B).
+ *
+ * This condition only applies if
+ * 1. A and B are in the same subscription group (e.c. for CBRS data switching) and
+ * 2. A was validated before the switch
+ *
+ * The goal of this is to minimize the flickering in the UI of the cellular indicator
+ */
+ private val forcingCellularValidation =
+ mobileConnectionsRepo.activeSubChangedInGroupEvent
+ .filter { mobileConnectionsRepo.defaultMobileNetworkConnectivity.value.isValidated }
+ .transformLatest {
+ emit(true)
+ delay(2000)
+ emit(false)
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
+
+ override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
+ combine(
+ mobileConnectionsRepo.defaultMobileNetworkConnectivity,
+ forcingCellularValidation,
+ ) { networkConnectivity, forceValidation ->
+ return@combine if (forceValidation) {
+ MobileConnectivityModel(
+ isValidated = true,
+ isConnected = networkConnectivity.isConnected
+ )
+ } else {
+ networkConnectivity
+ }
+ }
+ .stateIn(
+ scope,
+ SharingStarted.WhileSubscribed(),
+ mobileConnectionsRepo.defaultMobileNetworkConnectivity.value
+ )
+
/**
* Mapping from network type to [MobileIconGroup] using the config generated for the default
* subscription Id. This mapping is the same for every subscription.
@@ -207,8 +264,10 @@
activeDataConnectionHasDataEnabled,
alwaysShowDataRatIcon,
alwaysUseCdmaLevel,
+ defaultMobileNetworkConnectivity,
defaultMobileIconMapping,
defaultMobileIconGroup,
+ defaultDataSubId,
isDefaultConnectionFailed,
mobileConnectionsRepo.getRepoForSubId(subId),
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
index a2117c7..5e935616 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt
@@ -102,24 +102,29 @@
.stateIn(scope, SharingStarted.WhileSubscribed(), initial)
}
+ private val showNetworkTypeIcon: Flow<Boolean> =
+ combine(
+ iconInteractor.isDataConnected,
+ iconInteractor.isDataEnabled,
+ iconInteractor.isDefaultConnectionFailed,
+ iconInteractor.alwaysShowDataRatIcon,
+ iconInteractor.isConnected,
+ ) { dataConnected, dataEnabled, failedConnection, alwaysShow, connected ->
+ alwaysShow || (dataConnected && dataEnabled && !failedConnection && connected)
+ }
+
override val networkTypeIcon: Flow<Icon?> =
combine(
iconInteractor.networkTypeIconGroup,
- iconInteractor.isDataConnected,
- iconInteractor.isDataEnabled,
- iconInteractor.isDefaultConnectionFailed,
- iconInteractor.alwaysShowDataRatIcon,
- ) { networkTypeIconGroup, dataConnected, dataEnabled, failedConnection, alwaysShow ->
+ showNetworkTypeIcon,
+ ) { networkTypeIconGroup, shouldShow ->
val desc =
if (networkTypeIconGroup.dataContentDescription != 0)
ContentDescription.Resource(networkTypeIconGroup.dataContentDescription)
else null
val icon = Icon.Resource(networkTypeIconGroup.dataType, desc)
return@combine when {
- alwaysShow -> icon
- !dataConnected -> null
- !dataEnabled -> null
- failedConnection -> null
+ !shouldShow -> null
else -> icon
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
new file mode 100644
index 0000000..e092f01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/telephony/ui/activity/SwitchToManagedProfileForCallActivity.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.telephony.ui.activity
+
+import android.app.ActivityOptions
+import android.content.DialogInterface
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.os.UserHandle
+import android.util.Log
+import android.view.WindowManager
+import com.android.internal.app.AlertActivity
+import com.android.systemui.R
+
+/** Dialog shown to the user to switch to managed profile for making a call using work SIM. */
+class SwitchToManagedProfileForCallActivity : AlertActivity(), DialogInterface.OnClickListener {
+ private lateinit var phoneNumber: Uri
+ private var managedProfileUserId = UserHandle.USER_NULL
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ window.addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS
+ )
+ super.onCreate(savedInstanceState)
+
+ phoneNumber = intent.getData()
+ managedProfileUserId =
+ intent.getIntExtra(
+ "android.telecom.extra.MANAGED_PROFILE_USER_ID",
+ UserHandle.USER_NULL
+ )
+
+ mAlertParams.apply {
+ mTitle = getString(R.string.call_from_work_profile_title)
+ mMessage = getString(R.string.call_from_work_profile_text)
+ mPositiveButtonText = getString(R.string.call_from_work_profile_action)
+ mNegativeButtonText = getString(R.string.call_from_work_profile_close)
+ mPositiveButtonListener = this@SwitchToManagedProfileForCallActivity
+ mNegativeButtonListener = this@SwitchToManagedProfileForCallActivity
+ }
+ setupAlert()
+ }
+
+ override fun onClick(dialog: DialogInterface?, which: Int) {
+ if (which == BUTTON_POSITIVE) {
+ switchToManagedProfile()
+ }
+ finish()
+ }
+
+ private fun switchToManagedProfile() {
+ try {
+ applicationContext.startActivityAsUser(
+ Intent(Intent.ACTION_DIAL, phoneNumber),
+ ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
+ UserHandle.of(managedProfileUserId)
+ )
+ } catch (e: Exception) {
+ Log.e(TAG, "Failed to launch activity", e)
+ }
+ }
+
+ companion object {
+ private const val TAG = "SwitchToManagedProfileForCallActivity"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
index ad48e21..df8d161 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
@@ -31,6 +31,7 @@
import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS
import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT
import androidx.annotation.CallSuper
+import androidx.annotation.VisibleForTesting
import com.android.systemui.CoreStartable
import com.android.systemui.Dumpable
import com.android.systemui.dagger.qualifiers.Main
@@ -108,9 +109,10 @@
* Whenever the current view disappears, the next-priority view will be displayed if it's still
* valid.
*/
+ @VisibleForTesting
internal val activeViews: MutableList<DisplayInfo> = mutableListOf()
- private fun getCurrentDisplayInfo(): DisplayInfo? {
+ internal fun getCurrentDisplayInfo(): DisplayInfo? {
return activeViews.getOrNull(0)
}
@@ -119,15 +121,26 @@
dumpManager.registerNormalDumpable(this)
}
+ private val listeners: MutableSet<Listener> = mutableSetOf()
+
+ /** Registers a listener. */
+ fun registerListener(listener: Listener) {
+ listeners.add(listener)
+ }
+
+ /** Unregisters a listener. */
+ fun unregisterListener(listener: Listener) {
+ listeners.remove(listener)
+ }
+
/**
* Displays the view with the provided [newInfo].
*
* This method handles inflating and attaching the view, then delegates to [updateView] to
* display the correct information in the view.
- * @param onViewTimeout a runnable that runs after the view timeout.
*/
@Synchronized
- fun displayView(newInfo: T, onViewTimeout: Runnable? = null) {
+ fun displayView(newInfo: T) {
val timeout = accessibilityManager.getRecommendedTimeoutMillis(
newInfo.timeoutMs,
// Not all views have controls so FLAG_CONTENT_CONTROLS might be superfluous, but
@@ -146,14 +159,13 @@
logger.logViewUpdate(newInfo)
currentDisplayInfo.info = newInfo
currentDisplayInfo.timeExpirationMillis = timeExpirationMillis
- updateTimeout(currentDisplayInfo, timeout, onViewTimeout)
+ updateTimeout(currentDisplayInfo, timeout)
updateView(newInfo, view)
return
}
val newDisplayInfo = DisplayInfo(
info = newInfo,
- onViewTimeout = onViewTimeout,
timeExpirationMillis = timeExpirationMillis,
// Null values will be updated to non-null if/when this view actually gets displayed
view = null,
@@ -196,7 +208,7 @@
private fun showNewView(newDisplayInfo: DisplayInfo, timeout: Int) {
logger.logViewAddition(newDisplayInfo.info)
createAndAcquireWakeLock(newDisplayInfo)
- updateTimeout(newDisplayInfo, timeout, newDisplayInfo.onViewTimeout)
+ updateTimeout(newDisplayInfo, timeout)
inflateAndUpdateView(newDisplayInfo)
}
@@ -227,19 +239,16 @@
/**
* Creates a runnable that will remove [displayInfo] in [timeout] ms from now.
*
- * @param onViewTimeout an optional runnable that will be run if the view times out.
* @return a runnable that, when run, will *cancel* the view's timeout.
*/
- private fun updateTimeout(displayInfo: DisplayInfo, timeout: Int, onViewTimeout: Runnable?) {
+ private fun updateTimeout(displayInfo: DisplayInfo, timeout: Int) {
val cancelViewTimeout = mainExecutor.executeDelayed(
{
removeView(displayInfo.info.id, REMOVAL_REASON_TIMEOUT)
- onViewTimeout?.run()
},
timeout.toLong()
)
- displayInfo.onViewTimeout = onViewTimeout
// Cancel old view timeout and re-set it.
displayInfo.cancelViewTimeout?.run()
displayInfo.cancelViewTimeout = cancelViewTimeout
@@ -317,6 +326,9 @@
// event comes in while this view is animating out, we still display the new view
// appropriately.
activeViews.remove(displayInfo)
+ listeners.forEach {
+ it.onInfoPermanentlyRemoved(id)
+ }
// No need to time the view out since it's already gone
displayInfo.cancelViewTimeout?.run()
@@ -380,6 +392,9 @@
invalidViews.forEach {
activeViews.remove(it)
logger.logViewExpiration(it.info)
+ listeners.forEach { listener ->
+ listener.onInfoPermanentlyRemoved(it.info.id)
+ }
}
}
@@ -436,6 +451,15 @@
onAnimationEnd.run()
}
+ /** A listener interface to be notified of various view events. */
+ fun interface Listener {
+ /**
+ * Called whenever a [DisplayInfo] with the given [id] has been removed and will never be
+ * displayed again (unless another call to [updateView] is made).
+ */
+ fun onInfoPermanentlyRemoved(id: String)
+ }
+
/** A container for all the display-related state objects. */
inner class DisplayInfo(
/**
@@ -461,11 +485,6 @@
var wakeLock: WakeLock?,
/**
- * See [displayView].
- */
- var onViewTimeout: Runnable?,
-
- /**
* A runnable that, when run, will cancel this view's timeout.
*
* Null if this info isn't currently being displayed.
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
index 04b1a50..9e0bbb7 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
@@ -80,6 +80,7 @@
powerManager: PowerManager,
private val falsingManager: FalsingManager,
private val falsingCollector: FalsingCollector,
+ private val swipeChipbarAwayGestureHandler: SwipeChipbarAwayGestureHandler?,
private val viewUtil: ViewUtil,
private val vibratorHelper: VibratorHelper,
wakeLockBuilder: WakeLock.Builder,
@@ -105,6 +106,8 @@
commonWindowLayoutParams.apply { gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL) }
override fun updateView(newInfo: ChipbarInfo, currentView: ViewGroup) {
+ updateGestureListening()
+
logger.logViewUpdate(
newInfo.windowTitle,
newInfo.text.loadText(context),
@@ -228,6 +231,42 @@
includeMargins = true,
onAnimationEnd,
)
+
+ updateGestureListening()
+ }
+
+ private fun updateGestureListening() {
+ if (swipeChipbarAwayGestureHandler == null) {
+ return
+ }
+
+ val currentDisplayInfo = getCurrentDisplayInfo()
+ if (currentDisplayInfo != null && currentDisplayInfo.info.allowSwipeToDismiss) {
+ swipeChipbarAwayGestureHandler.setViewFetcher { currentDisplayInfo.view }
+ swipeChipbarAwayGestureHandler.addOnGestureDetectedCallback(TAG) {
+ onSwipeUpGestureDetected()
+ }
+ } else {
+ swipeChipbarAwayGestureHandler.resetViewFetcher()
+ swipeChipbarAwayGestureHandler.removeOnGestureDetectedCallback(TAG)
+ }
+ }
+
+ private fun onSwipeUpGestureDetected() {
+ val currentDisplayInfo = getCurrentDisplayInfo()
+ if (currentDisplayInfo == null) {
+ logger.logSwipeGestureError(id = null, errorMsg = "No info is being displayed")
+ return
+ }
+ if (!currentDisplayInfo.info.allowSwipeToDismiss) {
+ logger.logSwipeGestureError(
+ id = currentDisplayInfo.info.id,
+ errorMsg = "This view prohibits swipe-to-dismiss",
+ )
+ return
+ }
+ removeView(currentDisplayInfo.info.id, SWIPE_UP_GESTURE_REASON)
+ updateGestureListening()
}
private fun ViewGroup.getInnerView(): ViewGroup {
@@ -250,3 +289,5 @@
private const val ANIMATION_IN_DURATION = 500L
private const val ANIMATION_OUT_DURATION = 250L
@IdRes private val INFO_TAG = R.id.tag_chipbar_info
+private const val SWIPE_UP_GESTURE_REASON = "SWIPE_UP_GESTURE_DETECTED"
+private const val TAG = "ChipbarCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index dd4bd26..fe46318 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -33,12 +33,14 @@
* @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
* locales; on the left in RTL locales).
* @property vibrationEffect an optional vibration effect when the chipbar is displayed
+ * @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
*/
data class ChipbarInfo(
val startIcon: TintedIcon,
val text: Text,
val endItem: ChipbarEndItem?,
val vibrationEffect: VibrationEffect? = null,
+ val allowSwipeToDismiss: Boolean = false,
override val windowTitle: String,
override val wakeReason: String,
override val timeoutMs: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
index fcfbe0a..f239428 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
@@ -46,4 +46,16 @@
{ "Chipbar updated. window=$str1 text=$str2 endItem=$str3" }
)
}
+
+ fun logSwipeGestureError(id: String?, errorMsg: String) {
+ buffer.log(
+ tag,
+ LogLevel.WARNING,
+ {
+ str1 = id
+ str2 = errorMsg
+ },
+ { "Chipbar swipe gesture detected for incorrect state. id=$str1 error=$str2" }
+ )
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandler.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandler.kt
new file mode 100644
index 0000000..6e3cb48
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandler.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.temporarydisplay.chipbar
+
+import android.content.Context
+import android.view.MotionEvent
+import android.view.View
+import com.android.systemui.statusbar.gesture.SwipeUpGestureHandler
+import com.android.systemui.statusbar.gesture.SwipeUpGestureLogger
+import com.android.systemui.util.boundsOnScreen
+
+/**
+ * A class to detect when a user has swiped the chipbar away.
+ *
+ * Effectively [SysUISingleton]. But, this shouldn't be created if the gesture isn't enabled. See
+ * [TemporaryDisplayModule.provideSwipeChipbarAwayGestureHandler].
+ */
+class SwipeChipbarAwayGestureHandler(
+ context: Context,
+ logger: SwipeUpGestureLogger,
+) : SwipeUpGestureHandler(context, logger, loggerTag = LOGGER_TAG) {
+
+ private var viewFetcher: () -> View? = { null }
+
+ override fun startOfGestureIsWithinBounds(ev: MotionEvent): Boolean {
+ val view = viewFetcher.invoke() ?: return false
+ // Since chipbar is in its own window, we need to use [boundsOnScreen] to get an accurate
+ // bottom. ([view.bottom] would be relative to its window, which would be too small.)
+ val viewBottom = view.boundsOnScreen.bottom
+ // Allow the gesture to start a bit below the chipbar
+ return ev.y <= 1.5 * viewBottom
+ }
+
+ /**
+ * Sets a fetcher that returns the current chipbar view. The fetcher will be invoked whenever a
+ * gesture starts to determine if the gesture is near the chipbar.
+ */
+ fun setViewFetcher(fetcher: () -> View?) {
+ viewFetcher = fetcher
+ }
+
+ /** Removes the current view fetcher. */
+ fun resetViewFetcher() {
+ viewFetcher = { null }
+ }
+}
+
+private const val LOGGER_TAG = "SwipeChipbarAway"
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
index cf0a183..933c060 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
@@ -16,22 +16,38 @@
package com.android.systemui.temporarydisplay.dagger
+import android.content.Context
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.media.taptotransfer.MediaTttFlags
import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.statusbar.gesture.SwipeUpGestureLogger
+import com.android.systemui.temporarydisplay.chipbar.SwipeChipbarAwayGestureHandler
import dagger.Module
import dagger.Provides
@Module
interface TemporaryDisplayModule {
- @Module
companion object {
- @JvmStatic
@Provides
@SysUISingleton
@ChipbarLog
fun provideChipbarLogBuffer(factory: LogBufferFactory): LogBuffer {
return factory.create("ChipbarLog", 40)
}
+
+ @Provides
+ @SysUISingleton
+ fun provideSwipeChipbarAwayGestureHandler(
+ mediaTttFlags: MediaTttFlags,
+ context: Context,
+ logger: SwipeUpGestureLogger,
+ ): SwipeChipbarAwayGestureHandler? {
+ return if (mediaTttFlags.isMediaTttDismissGestureEnabled()) {
+ SwipeChipbarAwayGestureHandler(context, logger)
+ } else {
+ null
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 5894fd3..9f6e602 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -26,7 +26,6 @@
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_SOURCE;
import static com.android.systemui.theme.ThemeOverlayApplier.TIMESTAMP_FIELD;
-import android.annotation.Nullable;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.WallpaperManager.OnColorsChangedListener;
@@ -70,6 +69,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.monet.ColorScheme;
import com.android.systemui.monet.Style;
+import com.android.systemui.monet.TonalPalette;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -389,7 +389,7 @@
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mMainExecutor,
UserHandle.ALL);
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
+ Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
false,
new ContentObserver(mBgHandler) {
@Override
@@ -511,39 +511,42 @@
/**
* Given a color candidate, return an overlay definition.
*/
- protected @Nullable FabricatedOverlay getOverlay(int color, int type, Style style) {
+ protected FabricatedOverlay getOverlay(int color, int type, Style style) {
boolean nightMode = (mResources.getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
mColorScheme = new ColorScheme(color, nightMode, style);
- List<Integer> colorShades = type == ACCENT
- ? mColorScheme.getAllAccentColors() : mColorScheme.getAllNeutralColors();
String name = type == ACCENT ? "accent" : "neutral";
- int paletteSize = mColorScheme.getAccent1().size();
+
FabricatedOverlay.Builder overlay =
new FabricatedOverlay.Builder("com.android.systemui", name, "android");
- for (int i = 0; i < colorShades.size(); i++) {
- int luminosity = i % paletteSize;
- int paletteIndex = i / paletteSize + 1;
- String resourceName;
- switch (luminosity) {
- case 0:
- resourceName = "android:color/system_" + name + paletteIndex + "_10";
- break;
- case 1:
- resourceName = "android:color/system_" + name + paletteIndex + "_50";
- break;
- default:
- int l = luminosity - 1;
- resourceName = "android:color/system_" + name + paletteIndex + "_" + l + "00";
- }
- overlay.setResourceValue(resourceName, TypedValue.TYPE_INT_COLOR_ARGB8,
- ColorUtils.setAlphaComponent(colorShades.get(i), 0xFF));
+
+ if (type == ACCENT) {
+ assignTonalPaletteToOverlay("accent1", overlay, mColorScheme.getAccent1());
+ assignTonalPaletteToOverlay("accent2", overlay, mColorScheme.getAccent2());
+ assignTonalPaletteToOverlay("accent3", overlay, mColorScheme.getAccent3());
+ } else {
+ assignTonalPaletteToOverlay("neutral1", overlay, mColorScheme.getNeutral1());
+ assignTonalPaletteToOverlay("neutral2", overlay, mColorScheme.getNeutral2());
}
return overlay.build();
}
+ private void assignTonalPaletteToOverlay(String name,
+ FabricatedOverlay.Builder overlay, TonalPalette tonalPalette) {
+
+ String resourcePrefix = "android:color/system_" + name;
+ int colorDataType = TypedValue.TYPE_INT_COLOR_ARGB8;
+
+ tonalPalette.getAllShadesMapped().forEach((key, value) -> {
+ String resourceName = resourcePrefix + "_" + key;
+ int colorValue = ColorUtils.setAlphaComponent(value, 0xFF);
+ overlay.setResourceValue(resourceName, colorDataType,
+ colorValue);
+ });
+ }
+
/**
* Checks if the color scheme in mColorScheme matches the current system palettes.
* @param managedProfiles List of managed profiles for this user.
@@ -555,15 +558,15 @@
Resources res = userHandle.isSystem()
? mResources : mContext.createContextAsUser(userHandle, 0).getResources();
if (!(res.getColor(android.R.color.system_accent1_500, mContext.getTheme())
- == mColorScheme.getAccent1().get(6)
+ == mColorScheme.getAccent1().getS500()
&& res.getColor(android.R.color.system_accent2_500, mContext.getTheme())
- == mColorScheme.getAccent2().get(6)
+ == mColorScheme.getAccent2().getS500()
&& res.getColor(android.R.color.system_accent3_500, mContext.getTheme())
- == mColorScheme.getAccent3().get(6)
+ == mColorScheme.getAccent3().getS500()
&& res.getColor(android.R.color.system_neutral1_500, mContext.getTheme())
- == mColorScheme.getNeutral1().get(6)
+ == mColorScheme.getNeutral1().getS500()
&& res.getColor(android.R.color.system_neutral2_500, mContext.getTheme())
- == mColorScheme.getNeutral2().get(6))) {
+ == mColorScheme.getNeutral2().getS500())) {
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
index 523cf68..0069bb5 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
@@ -36,6 +36,8 @@
import android.view.WindowManager
import android.view.WindowlessWindowManager
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.LightRevealEffect
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.LinearLightRevealEffect
@@ -57,6 +59,7 @@
@Inject
constructor(
private val context: Context,
+ private val featureFlags: FeatureFlags,
private val deviceStateManager: DeviceStateManager,
private val contentResolver: ContentResolver,
private val displayManager: DisplayManager,
@@ -81,6 +84,7 @@
private var scrimView: LightRevealScrim? = null
private var isFolded: Boolean = false
private var isUnfoldHandled: Boolean = true
+ private var overlayAddReason: AddOverlayReason? = null
private var currentRotation: Int = context.display!!.rotation
@@ -158,6 +162,8 @@
ensureInBackground()
ensureOverlayRemoved()
+ overlayAddReason = reason
+
val newRoot = SurfaceControlViewHost(context, context.display!!, wwm)
val params = getLayoutParams()
val newView =
@@ -170,11 +176,7 @@
.apply {
revealEffect = createLightRevealEffect()
isScrimOpaqueChangedListener = Consumer {}
- revealAmount =
- when (reason) {
- FOLD -> TRANSPARENT
- UNFOLD -> BLACK
- }
+ revealAmount = calculateRevealAmount()
}
newRoot.setView(newView, params)
@@ -207,6 +209,31 @@
root = newRoot
}
+ private fun calculateRevealAmount(animationProgress: Float? = null): Float {
+ val overlayAddReason = overlayAddReason ?: UNFOLD
+
+ if (animationProgress == null) {
+ // Animation progress is unknown, calculate the initial value based on the overlay
+ // add reason
+ return when (overlayAddReason) {
+ FOLD -> TRANSPARENT
+ UNFOLD -> BLACK
+ }
+ }
+
+ val showVignetteWhenFolding =
+ featureFlags.isEnabled(Flags.ENABLE_DARK_VIGNETTE_WHEN_FOLDING)
+
+ return if (!showVignetteWhenFolding && overlayAddReason == FOLD) {
+ // Do not darken the content when SHOW_VIGNETTE_WHEN_FOLDING flag is off
+ // and we are folding the device. We still add the overlay to block touches
+ // while the animation is running but the overlay is transparent.
+ TRANSPARENT
+ } else {
+ animationProgress
+ }
+ }
+
private fun getLayoutParams(): WindowManager.LayoutParams {
val params: WindowManager.LayoutParams = WindowManager.LayoutParams()
@@ -259,7 +286,7 @@
private inner class TransitionListener : TransitionProgressListener {
override fun onTransitionProgress(progress: Float) {
- executeInBackground { scrimView?.revealAmount = progress }
+ executeInBackground { scrimView?.revealAmount = calculateRevealAmount(progress) }
}
override fun onTransitionFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
index c570ec8..977cf0e 100644
--- a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
@@ -31,10 +31,12 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.users.EditUserInfoController;
import com.android.settingslib.users.GrantAdminDialogController;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.user.utils.MultiUserActionsEvent;
import javax.inject.Inject;
@@ -60,7 +62,7 @@
private final EditUserInfoController mEditUserInfoController;
private final IActivityManager mActivityManager;
private final ActivityStarter mActivityStarter;
-
+ private final UiEventLogger mUiEventLogger;
private Dialog mGrantAdminDialog;
private Dialog mSetupUserDialog;
private final OnBackInvokedCallback mBackCallback = this::onBackInvoked;
@@ -68,11 +70,12 @@
@Inject
public CreateUserActivity(UserCreator userCreator,
EditUserInfoController editUserInfoController, IActivityManager activityManager,
- ActivityStarter activityStarter) {
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger) {
mUserCreator = userCreator;
mEditUserInfoController = editUserInfoController;
mActivityManager = activityManager;
mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
}
@Override
@@ -128,12 +131,22 @@
);
}
+ /**
+ * Returns dialog that allows to grant user admin rights.
+ */
private Dialog buildGrantAdminDialog() {
return new GrantAdminDialogController().createDialog(
this,
(grantAdminRights) -> {
mGrantAdminDialog.dismiss();
mGrantAdminRights = grantAdminRights;
+ if (mGrantAdminRights) {
+ mUiEventLogger.log(MultiUserActionsEvent
+ .GRANT_ADMIN_FROM_USER_SWITCHER_CREATION_DIALOG);
+ } else {
+ mUiEventLogger.log(MultiUserActionsEvent
+ .NOT_GRANT_ADMIN_FROM_USER_SWITCHER_CREATION_DIALOG);
+ }
mSetupUserDialog = createDialog();
mSetupUserDialog.show();
},
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index c0f0390..8cb4deb 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -174,7 +174,7 @@
val callback =
object : UserTracker.Callback {
- override fun onUserChanged(newUser: Int, userContext: Context) {
+ override fun onUserChanging(newUser: Int, userContext: Context) {
send()
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/AddUserDialog.kt b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/AddUserDialog.kt
index a9d66de..5a25a4e 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/AddUserDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/AddUserDialog.kt
@@ -63,11 +63,10 @@
}
// Use broadcast instead of ShadeController, as this dialog may have started in
- // another
- // process where normal dagger bindings are not available.
+ // another process where normal dagger bindings are not available.
broadcastSender.sendBroadcastAsUser(
Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
- UserHandle.CURRENT
+ userHandle
)
context.startActivityAsUser(
diff --git a/packages/SystemUI/src/com/android/systemui/user/utils/MultiUserActionsEvent.kt b/packages/SystemUI/src/com/android/systemui/user/utils/MultiUserActionsEvent.kt
index ec79b6d..c1c2419 100644
--- a/packages/SystemUI/src/com/android/systemui/user/utils/MultiUserActionsEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/utils/MultiUserActionsEvent.kt
@@ -29,7 +29,11 @@
@UiEvent(doc = "Switch to Guest User tap from User Switcher.")
SWITCH_TO_GUEST_FROM_USER_SWITCHER(1267),
@UiEvent(doc = "Switch to Restricted User tap from User Switcher.")
- SWITCH_TO_RESTRICTED_USER_FROM_USER_SWITCHER(1268);
+ SWITCH_TO_RESTRICTED_USER_FROM_USER_SWITCHER(1268),
+ @UiEvent(doc = "Grant admin privileges to user on creation from User Switcher.")
+ GRANT_ADMIN_FROM_USER_SWITCHER_CREATION_DIALOG(1278),
+ @UiEvent(doc = "Not grant admin privileges to user on creation from User Switcher")
+ NOT_GRANT_ADMIN_FROM_USER_SWITCHER_CREATION_DIALOG(1279);
override fun getId(): Int {
return value
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
index b61b2e6..47d505e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
@@ -16,14 +16,21 @@
package com.android.systemui.util.kotlin
+import com.android.systemui.util.time.SystemClock
+import com.android.systemui.util.time.SystemClockImpl
+import kotlinx.coroutines.CoroutineStart
import java.util.concurrent.atomic.AtomicReference
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
+import kotlin.math.max
/**
* Returns a new [Flow] that combines the two most recent emissions from [this] using [transform].
@@ -167,3 +174,89 @@
* Note that the returned Flow will not emit anything until [other] has emitted at least one value.
*/
fun <A> Flow<*>.sample(other: Flow<A>): Flow<A> = sample(other) { _, a -> a }
+
+/**
+ * Returns a flow that mirrors the original flow, but delays values following emitted values for the
+ * given [periodMs]. If the original flow emits more than one value during this period, only the
+ * latest value is emitted.
+ *
+ * Example:
+ *
+ * ```kotlin
+ * flow {
+ * emit(1) // t=0ms
+ * delay(90)
+ * emit(2) // t=90ms
+ * delay(90)
+ * emit(3) // t=180ms
+ * delay(1010)
+ * emit(4) // t=1190ms
+ * delay(1010)
+ * emit(5) // t=2200ms
+ * }.throttle(1000)
+ * ```
+ *
+ * produces the following emissions at the following times
+ *
+ * ```text
+ * 1 (t=0ms), 3 (t=1000ms), 4 (t=2000ms), 5 (t=3000ms)
+ * ```
+ */
+fun <T> Flow<T>.throttle(periodMs: Long): Flow<T> = this.throttle(periodMs, SystemClockImpl())
+
+/**
+ * Returns a flow that mirrors the original flow, but delays values following emitted values for the
+ * given [periodMs] as reported by the given [clock]. If the original flow emits more than one value
+ * during this period, only The latest value is emitted.
+ *
+ * Example:
+ *
+ * ```kotlin
+ * flow {
+ * emit(1) // t=0ms
+ * delay(90)
+ * emit(2) // t=90ms
+ * delay(90)
+ * emit(3) // t=180ms
+ * delay(1010)
+ * emit(4) // t=1190ms
+ * delay(1010)
+ * emit(5) // t=2200ms
+ * }.throttle(1000)
+ * ```
+ *
+ * produces the following emissions at the following times
+ *
+ * ```text
+ * 1 (t=0ms), 3 (t=1000ms), 4 (t=2000ms), 5 (t=3000ms)
+ * ```
+ */
+fun <T> Flow<T>.throttle(periodMs: Long, clock: SystemClock): Flow<T> = channelFlow {
+ coroutineScope {
+ var previousEmitTimeMs = 0L
+ var delayJob: Job? = null
+ var sendJob: Job? = null
+ val outerScope = this
+
+ collect {
+ delayJob?.cancel()
+ sendJob?.join()
+ val currentTimeMs = clock.elapsedRealtime()
+ val timeSinceLastEmit = currentTimeMs - previousEmitTimeMs
+ val timeUntilNextEmit = max(0L, periodMs - timeSinceLastEmit)
+ if (timeUntilNextEmit > 0L) {
+ // We create delayJob to allow cancellation during the delay period
+ delayJob = launch {
+ delay(timeUntilNextEmit)
+ sendJob = outerScope.launch(start = CoroutineStart.UNDISPATCHED) {
+ send(it)
+ previousEmitTimeMs = clock.elapsedRealtime()
+ }
+ }
+ } else {
+ send(it)
+ previousEmitTimeMs = currentTimeMs
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index 4351afe..a0d22f3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -29,12 +29,12 @@
import android.net.Uri;
import android.os.Debug;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.util.Log;
import androidx.core.content.FileProvider;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.settings.UserTracker;
import com.google.android.collect.Lists;
@@ -62,13 +62,15 @@
static final String LEAK_DUMP = "leak.dump";
private final Context mContext;
+ private final UserTracker mUserTracker;
private final LeakDetector mLeakDetector;
private final String mLeakReportEmail;
@Inject
- public LeakReporter(Context context, LeakDetector leakDetector,
+ public LeakReporter(Context context, UserTracker userTracker, LeakDetector leakDetector,
@Nullable @Named(LEAK_REPORT_EMAIL_NAME) String leakReportEmail) {
mContext = context;
+ mUserTracker = userTracker;
mLeakDetector = leakDetector;
mLeakReportEmail = leakReportEmail;
}
@@ -111,7 +113,7 @@
getIntent(hprofFile, dumpFile),
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
null,
- UserHandle.CURRENT));
+ mUserTracker.getUserHandle()));
notiMan.notify(TAG, 0, builder.build());
} catch (IOException e) {
Log.e(TAG, "Couldn't dump heap for leak", e);
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java b/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java
index 1a30b0a..85fada2 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/GlobalSettingsImpl.java
@@ -20,14 +20,18 @@
import android.net.Uri;
import android.provider.Settings;
+import com.android.systemui.settings.UserTracker;
+
import javax.inject.Inject;
class GlobalSettingsImpl implements GlobalSettings {
private final ContentResolver mContentResolver;
+ private final UserTracker mUserTracker;
@Inject
- GlobalSettingsImpl(ContentResolver contentResolver) {
+ GlobalSettingsImpl(ContentResolver contentResolver, UserTracker userTracker) {
mContentResolver = contentResolver;
+ mUserTracker = userTracker;
}
@Override
@@ -36,13 +40,19 @@
}
@Override
+ public UserTracker getUserTracker() {
+ return mUserTracker;
+ }
+
+ @Override
public Uri getUriFor(String name) {
return Settings.Global.getUriFor(name);
}
@Override
public String getStringForUser(String name, int userHandle) {
- return Settings.Global.getStringForUser(mContentResolver, name, userHandle);
+ return Settings.Global.getStringForUser(mContentResolver, name,
+ getRealUserHandle(userHandle));
}
@Override
@@ -53,14 +63,16 @@
@Override
public boolean putStringForUser(String name, String value, int userHandle) {
- return Settings.Global.putStringForUser(mContentResolver, name, value, userHandle);
+ return Settings.Global.putStringForUser(mContentResolver, name, value,
+ getRealUserHandle(userHandle));
}
@Override
public boolean putStringForUser(String name, String value, String tag, boolean makeDefault,
int userHandle, boolean overrideableByRestore) {
return Settings.Global.putStringForUser(
- mContentResolver, name, value, tag, makeDefault, userHandle, overrideableByRestore);
+ mContentResolver, name, value, tag, makeDefault, getRealUserHandle(userHandle),
+ overrideableByRestore);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java b/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
index 020c234..f995436 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java
@@ -20,14 +20,18 @@
import android.net.Uri;
import android.provider.Settings;
+import com.android.systemui.settings.UserTracker;
+
import javax.inject.Inject;
class SecureSettingsImpl implements SecureSettings {
private final ContentResolver mContentResolver;
+ private final UserTracker mUserTracker;
@Inject
- SecureSettingsImpl(ContentResolver contentResolver) {
+ SecureSettingsImpl(ContentResolver contentResolver, UserTracker userTracker) {
mContentResolver = contentResolver;
+ mUserTracker = userTracker;
}
@Override
@@ -36,13 +40,19 @@
}
@Override
+ public UserTracker getUserTracker() {
+ return mUserTracker;
+ }
+
+ @Override
public Uri getUriFor(String name) {
return Settings.Secure.getUriFor(name);
}
@Override
public String getStringForUser(String name, int userHandle) {
- return Settings.Secure.getStringForUser(mContentResolver, name, userHandle);
+ return Settings.Secure.getStringForUser(mContentResolver, name,
+ getRealUserHandle(userHandle));
}
@Override
@@ -52,14 +62,16 @@
@Override
public boolean putStringForUser(String name, String value, int userHandle) {
- return Settings.Secure.putStringForUser(mContentResolver, name, value, userHandle);
+ return Settings.Secure.putStringForUser(mContentResolver, name, value,
+ getRealUserHandle(userHandle));
}
@Override
public boolean putStringForUser(String name, String value, String tag, boolean makeDefault,
int userHandle, boolean overrideableByRestore) {
return Settings.Secure.putStringForUser(
- mContentResolver, name, value, tag, makeDefault, userHandle, overrideableByRestore);
+ mContentResolver, name, value, tag, makeDefault, getRealUserHandle(userHandle),
+ overrideableByRestore);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
index 1bf5f07..b6846a3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxy.java
@@ -22,8 +22,11 @@
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.UserHandle;
import android.provider.Settings;
+import com.android.systemui.settings.UserTracker;
+
/**
* Used to interact with Settings.Secure, Settings.Global, and Settings.System.
*
@@ -46,6 +49,11 @@
ContentResolver getContentResolver();
/**
+ * Returns that {@link UserTracker} this instance was constructed with.
+ */
+ UserTracker getUserTracker();
+
+ /**
* Returns the user id for the associated {@link ContentResolver}.
*/
default int getUserId() {
@@ -53,6 +61,17 @@
}
/**
+ * Returns the actual current user handle when querying with the current user. Otherwise,
+ * returns the passed in user id.
+ */
+ default int getRealUserHandle(int userHandle) {
+ if (userHandle != UserHandle.USER_CURRENT) {
+ return userHandle;
+ }
+ return getUserTracker().getUserId();
+ }
+
+ /**
* Construct the content URI for a particular name/value pair,
* useful for monitoring changes with a ContentObserver.
* @param name to look up in the table
@@ -84,18 +103,18 @@
*
* Implicitly calls {@link #getUriFor(String)} on the passed in name.
*/
- default void registerContentObserver(String name, boolean notifyForDescendents,
+ default void registerContentObserver(String name, boolean notifyForDescendants,
ContentObserver settingsObserver) {
- registerContentObserver(getUriFor(name), notifyForDescendents, settingsObserver);
+ registerContentObserver(getUriFor(name), notifyForDescendants, settingsObserver);
}
/**
* Convenience wrapper around
* {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver)}.'
*/
- default void registerContentObserver(Uri uri, boolean notifyForDescendents,
+ default void registerContentObserver(Uri uri, boolean notifyForDescendants,
ContentObserver settingsObserver) {
- registerContentObserverForUser(uri, notifyForDescendents, settingsObserver, getUserId());
+ registerContentObserverForUser(uri, notifyForDescendants, settingsObserver, getUserId());
}
/**
@@ -127,10 +146,10 @@
* Implicitly calls {@link #getUriFor(String)} on the passed in name.
*/
default void registerContentObserverForUser(
- String name, boolean notifyForDescendents, ContentObserver settingsObserver,
+ String name, boolean notifyForDescendants, ContentObserver settingsObserver,
int userHandle) {
registerContentObserverForUser(
- getUriFor(name), notifyForDescendents, settingsObserver, userHandle);
+ getUriFor(name), notifyForDescendants, settingsObserver, userHandle);
}
/**
@@ -138,10 +157,10 @@
* {@link ContentResolver#registerContentObserver(Uri, boolean, ContentObserver, int)}
*/
default void registerContentObserverForUser(
- Uri uri, boolean notifyForDescendents, ContentObserver settingsObserver,
+ Uri uri, boolean notifyForDescendants, ContentObserver settingsObserver,
int userHandle) {
getContentResolver().registerContentObserver(
- uri, notifyForDescendents, settingsObserver, userHandle);
+ uri, notifyForDescendants, settingsObserver, getRealUserHandle(userHandle));
}
/** See {@link ContentResolver#unregisterContentObserver(ContentObserver)}. */
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt
index 0b8257d..561495e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SettingsProxyExt.kt
@@ -19,7 +19,6 @@
import android.annotation.UserIdInt
import android.database.ContentObserver
-import android.os.UserHandle
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -29,8 +28,8 @@
/** Returns a flow of [Unit] that is invoked each time that content is updated. */
fun SettingsProxy.observerFlow(
+ @UserIdInt userId: Int,
vararg names: String,
- @UserIdInt userId: Int = UserHandle.USER_CURRENT,
): Flow<Unit> {
return conflatedCallbackFlow {
val observer =
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java b/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
index 0dbb76f..fba7ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java
@@ -20,14 +20,18 @@
import android.net.Uri;
import android.provider.Settings;
+import com.android.systemui.settings.UserTracker;
+
import javax.inject.Inject;
class SystemSettingsImpl implements SystemSettings {
private final ContentResolver mContentResolver;
+ private final UserTracker mUserTracker;
@Inject
- SystemSettingsImpl(ContentResolver contentResolver) {
+ SystemSettingsImpl(ContentResolver contentResolver, UserTracker userTracker) {
mContentResolver = contentResolver;
+ mUserTracker = userTracker;
}
@Override
@@ -36,13 +40,19 @@
}
@Override
+ public UserTracker getUserTracker() {
+ return mUserTracker;
+ }
+
+ @Override
public Uri getUriFor(String name) {
return Settings.System.getUriFor(name);
}
@Override
public String getStringForUser(String name, int userHandle) {
- return Settings.System.getStringForUser(mContentResolver, name, userHandle);
+ return Settings.System.getStringForUser(mContentResolver, name,
+ getRealUserHandle(userHandle));
}
@Override
@@ -52,7 +62,8 @@
@Override
public boolean putStringForUser(String name, String value, int userHandle) {
- return Settings.System.putStringForUser(mContentResolver, name, value, userHandle);
+ return Settings.System.putStringForUser(mContentResolver, name, value,
+ getRealUserHandle(userHandle));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index f71d988..a453726 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -25,6 +25,7 @@
import android.provider.Settings;
import android.view.WindowManager.LayoutParams;
+import com.android.internal.R;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.demomode.DemoMode;
@@ -55,7 +56,7 @@
public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent";
public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
- public static final boolean DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT = false;
+ private final boolean mDefaultVolumeDownToEnterSilent;
public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
@@ -72,12 +73,7 @@
private final KeyguardViewMediator mKeyguardViewMediator;
private final ActivityStarter mActivityStarter;
private VolumeDialog mDialog;
- private VolumePolicy mVolumePolicy = new VolumePolicy(
- DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT, // volumeDownToEnterSilent
- DEFAULT_VOLUME_UP_TO_EXIT_SILENT, // volumeUpToExitSilent
- DEFAULT_DO_NOT_DISTURB_WHEN_SILENT, // doNotDisturbWhenSilent
- 400 // vibrateToSilentDebounce
- );
+ private VolumePolicy mVolumePolicy;
@Inject
public VolumeDialogComponent(
@@ -107,7 +103,20 @@
mDialog = dialog;
mDialog.init(LayoutParams.TYPE_VOLUME_OVERLAY, mVolumeDialogCallback);
}).build();
+
+
+ mDefaultVolumeDownToEnterSilent = mContext.getResources()
+ .getBoolean(R.bool.config_volume_down_to_enter_silent);
+
+ mVolumePolicy = new VolumePolicy(
+ mDefaultVolumeDownToEnterSilent, // volumeDownToEnterSilent
+ DEFAULT_VOLUME_UP_TO_EXIT_SILENT, // volumeUpToExitSilent
+ DEFAULT_DO_NOT_DISTURB_WHEN_SILENT, // doNotDisturbWhenSilent
+ 400 // vibrateToSilentDebounce
+ );
+
applyConfiguration();
+
tunerService.addTunable(this, VOLUME_DOWN_SILENT, VOLUME_UP_SILENT,
VOLUME_SILENT_DO_NOT_DISTURB);
demoModeController.addCallback(this);
@@ -121,7 +130,7 @@
if (VOLUME_DOWN_SILENT.equals(key)) {
volumeDownToEnterSilent =
- TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_DOWN_TO_ENTER_SILENT);
+ TunerService.parseIntegerSwitch(newValue, mDefaultVolumeDownToEnterSilent);
} else if (VOLUME_UP_SILENT.equals(key)) {
volumeUpToExitSilent =
TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_UP_TO_EXIT_SILENT);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 2fc8b03..d39a53d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -47,7 +47,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.os.VibrationEffect;
import android.provider.Settings;
import android.service.notification.Condition;
@@ -70,6 +69,7 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.RingerModeLiveData;
import com.android.systemui.util.RingerModeTracker;
@@ -134,6 +134,7 @@
private final CaptioningManager mCaptioningManager;
private final KeyguardManager mKeyguardManager;
private final ActivityManager mActivityManager;
+ private final UserTracker mUserTracker;
protected C mCallbacks = new C();
private final State mState = new State();
protected final MediaSessionsCallbacks mMediaSessionsCallbacksW;
@@ -181,6 +182,7 @@
CaptioningManager captioningManager,
KeyguardManager keyguardManager,
ActivityManager activityManager,
+ UserTracker userTracker,
DumpManager dumpManager
) {
mContext = context.getApplicationContext();
@@ -210,6 +212,7 @@
mCaptioningManager = captioningManager;
mKeyguardManager = keyguardManager;
mActivityManager = activityManager;
+ mUserTracker = userTracker;
dumpManager.registerDumpable("VolumeDialogControllerImpl", this);
boolean accessibilityVolumeStreamActive = accessibilityManager
@@ -372,7 +375,7 @@
if (System.currentTimeMillis() - mLastToggledRingerOn < TOUCH_FEEDBACK_TIMEOUT_MS) {
try {
mAudioService.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD,
- UserHandle.USER_CURRENT);
+ mUserTracker.getUserId());
} catch (RemoteException e) {
// ignore
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 4cbc709..4da5d49 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -273,7 +273,7 @@
};
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT),
+ Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
false /* notifyForDescendants */,
mDefaultPaymentAppObserver,
UserHandle.USER_ALL);
@@ -293,7 +293,7 @@
};
mSecureSettings.registerContentObserverForUser(
- Settings.Secure.getUriFor(QuickAccessWalletClientImpl.SETTING_KEY),
+ QuickAccessWalletClientImpl.SETTING_KEY,
false /* notifyForDescendants */,
mWalletPreferenceObserver,
UserHandle.USER_ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt
new file mode 100644
index 0000000..7b8235a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.wallet.controller
+
+import android.Manifest
+import android.content.Context
+import android.content.IntentFilter
+import android.service.quickaccesswallet.GetWalletCardsError
+import android.service.quickaccesswallet.GetWalletCardsResponse
+import android.service.quickaccesswallet.QuickAccessWalletClient
+import android.service.quickaccesswallet.WalletCard
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.shareIn
+
+@SysUISingleton
+class WalletContextualSuggestionsController
+@Inject
+constructor(
+ @Application private val applicationCoroutineScope: CoroutineScope,
+ private val walletController: QuickAccessWalletController,
+ broadcastDispatcher: BroadcastDispatcher,
+ featureFlags: FeatureFlags
+) {
+ private val allWalletCards: Flow<List<WalletCard>> =
+ if (featureFlags.isEnabled(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS)) {
+ conflatedCallbackFlow {
+ val callback =
+ object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
+ override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
+ trySendWithFailureLogging(response.walletCards, TAG)
+ }
+
+ override fun onWalletCardRetrievalError(error: GetWalletCardsError) {
+ trySendWithFailureLogging(emptyList<WalletCard>(), TAG)
+ }
+ }
+
+ walletController.setupWalletChangeObservers(
+ callback,
+ QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE,
+ QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE
+ )
+ walletController.updateWalletPreference()
+ walletController.queryWalletCards(callback)
+
+ awaitClose {
+ walletController.unregisterWalletChangeObservers(
+ QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE,
+ QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE
+ )
+ }
+ }
+ } else {
+ emptyFlow()
+ }
+
+ private val contextualSuggestionsCardIds: Flow<Set<String>> =
+ if (featureFlags.isEnabled(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS)) {
+ broadcastDispatcher.broadcastFlow(
+ filter = IntentFilter(ACTION_UPDATE_WALLET_CONTEXTUAL_SUGGESTIONS),
+ permission = Manifest.permission.BIND_QUICK_ACCESS_WALLET_SERVICE,
+ flags = Context.RECEIVER_EXPORTED
+ ) { intent, _ ->
+ if (intent.hasExtra(UPDATE_CARD_IDS_EXTRA)) {
+ intent.getStringArrayListExtra(UPDATE_CARD_IDS_EXTRA).toSet()
+ } else {
+ emptySet()
+ }
+ }
+ } else {
+ emptyFlow()
+ }
+
+ val contextualSuggestionCards: Flow<List<WalletCard>> =
+ combine(allWalletCards, contextualSuggestionsCardIds) { cards, ids ->
+ cards.filter { card -> ids.contains(card.cardId) }
+ }
+ .shareIn(applicationCoroutineScope, replay = 1, started = SharingStarted.Eagerly)
+
+ companion object {
+ private const val ACTION_UPDATE_WALLET_CONTEXTUAL_SUGGESTIONS =
+ "com.android.systemui.wallet.UPDATE_CONTEXTUAL_SUGGESTIONS"
+
+ private const val UPDATE_CARD_IDS_EXTRA = "cardIds"
+
+ private const val TAG = "WalletSuggestions"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
index 51742990..31df3bc 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java
@@ -28,7 +28,6 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Trace;
-import android.os.UserHandle;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Surface;
@@ -39,6 +38,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.DelayableExecutor;
import java.io.FileDescriptor;
@@ -60,6 +60,8 @@
private volatile int mPages = 1;
private boolean mPagesComputed = false;
+ private final UserTracker mUserTracker;
+
// used to handle WallpaperService messages (e.g. DO_ATTACH, MSG_UPDATE_SURFACE)
// and to receive WallpaperService callbacks (e.g. onCreateEngine, onSurfaceRedrawNeeded)
private HandlerThread mWorker;
@@ -72,9 +74,11 @@
private static final int DELAY_UNLOAD_BITMAP = 2000;
@Inject
- public ImageWallpaper(@Background DelayableExecutor backgroundExecutor) {
+ public ImageWallpaper(@Background DelayableExecutor backgroundExecutor,
+ UserTracker userTracker) {
super();
mBackgroundExecutor = backgroundExecutor;
+ mUserTracker = userTracker;
}
@Override
@@ -310,7 +314,7 @@
boolean loadSuccess = false;
Bitmap bitmap;
try {
- bitmap = mWallpaperManager.getBitmapAsUser(UserHandle.USER_CURRENT, false);
+ bitmap = mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false);
if (bitmap != null
&& bitmap.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) {
throw new RuntimeException("Wallpaper is too large to draw!");
@@ -322,9 +326,9 @@
// default wallpaper can't be loaded.
Log.w(TAG, "Unable to load wallpaper!", exception);
mWallpaperManager.clearWallpaper(
- WallpaperManager.FLAG_SYSTEM, UserHandle.USER_CURRENT);
+ WallpaperManager.FLAG_SYSTEM, mUserTracker.getUserId());
try {
- bitmap = mWallpaperManager.getBitmapAsUser(UserHandle.USER_CURRENT, false);
+ bitmap = mWallpaperManager.getBitmapAsUser(mUserTracker.getUserId(), false);
} catch (RuntimeException | OutOfMemoryError e) {
Log.w(TAG, "Unable to load default wallpaper!", e);
bitmap = null;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 9a9acf3..a4180fd 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -29,7 +29,6 @@
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
@@ -275,7 +274,7 @@
ArgumentCaptor<ContentObserver> observerCaptor =
ArgumentCaptor.forClass(ContentObserver.class);
mController.init();
- verify(mSecureSettings).registerContentObserverForUser(any(Uri.class),
+ verify(mSecureSettings).registerContentObserverForUser(any(String.class),
anyBoolean(), observerCaptor.capture(), eq(UserHandle.USER_ALL));
ContentObserver observer = observerCaptor.getValue();
mExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
index 7aa4763..4a5c1be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonModeObserverTest.java
@@ -22,14 +22,16 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-import android.os.UserHandle;
+import android.app.ActivityManager;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import org.junit.Before;
import org.junit.Rule;
@@ -42,11 +44,14 @@
@RunWith(AndroidTestingRunner.class)
@SmallTest
public class AccessibilityButtonModeObserverTest extends SysuiTestCase {
+ private static final int MY_USER_ID = ActivityManager.getCurrentUser();
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Mock
+ private UserTracker mUserTracker;
+ @Mock
private AccessibilityButtonModeObserver.ModeChangedListener mListener;
private AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
@@ -56,10 +61,12 @@
@Before
public void setUp() {
+ when(mUserTracker.getUserId()).thenReturn(MY_USER_ID);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
- Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, UserHandle.USER_CURRENT);
- mAccessibilityButtonModeObserver = new AccessibilityButtonModeObserver(mContext);
+ Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, MY_USER_ID);
+ mAccessibilityButtonModeObserver = new AccessibilityButtonModeObserver(mContext,
+ mUserTracker);
}
@Test
@@ -67,7 +74,7 @@
mAccessibilityButtonModeObserver.addListener(mListener);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, TEST_A11Y_BTN_MODE_VALUE,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
mAccessibilityButtonModeObserver.mContentObserver.onChange(false);
@@ -80,7 +87,7 @@
mAccessibilityButtonModeObserver.removeListener(mListener);
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, TEST_A11Y_BTN_MODE_VALUE,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
mAccessibilityButtonModeObserver.mContentObserver.onChange(false);
@@ -91,7 +98,7 @@
public void getCurrentAccessibilityButtonMode_expectedValue() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, TEST_A11Y_BTN_MODE_VALUE,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
final int actualValue =
mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
index 4145437..a5a7a4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityButtonTargetsObserverTest.java
@@ -21,14 +21,16 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-import android.os.UserHandle;
+import android.app.ActivityManager;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import org.junit.Before;
import org.junit.Rule;
@@ -42,11 +44,14 @@
@RunWith(AndroidTestingRunner.class)
@SmallTest
public class AccessibilityButtonTargetsObserverTest extends SysuiTestCase {
+ private static final int MY_USER_ID = ActivityManager.getCurrentUser();
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Mock
+ private UserTracker mUserTracker;
+ @Mock
private AccessibilityButtonTargetsObserver.TargetsChangedListener mListener;
private AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
@@ -55,7 +60,9 @@
@Before
public void setUp() {
- mAccessibilityButtonTargetsObserver = new AccessibilityButtonTargetsObserver(mContext);
+ when(mUserTracker.getUserId()).thenReturn(MY_USER_ID);
+ mAccessibilityButtonTargetsObserver = new AccessibilityButtonTargetsObserver(mContext,
+ mUserTracker);
}
@Test
@@ -63,7 +70,7 @@
mAccessibilityButtonTargetsObserver.addListener(mListener);
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
mAccessibilityButtonTargetsObserver.mContentObserver.onChange(false);
@@ -76,7 +83,7 @@
mAccessibilityButtonTargetsObserver.removeListener(mListener);
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
mAccessibilityButtonTargetsObserver.mContentObserver.onChange(false);
@@ -87,7 +94,7 @@
public void getCurrentAccessibilityButtonTargets_expectedValue() {
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ MY_USER_ID);
final String actualValue =
mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
index 58b4af4..47dff51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
@@ -40,6 +40,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +74,8 @@
private IRemoteMagnificationAnimationCallback mAnimationCallback;
@Mock
private OverviewProxyService mOverviewProxyService;
+ @Mock
+ private SecureSettings mSecureSettings;
private IWindowMagnificationConnection mIWindowMagnificationConnection;
private WindowMagnification mWindowMagnification;
@@ -88,7 +91,7 @@
any(IWindowMagnificationConnection.class));
mWindowMagnification = new WindowMagnification(getContext(),
getContext().getMainThreadHandler(), mCommandQueue,
- mModeSwitchesController, mSysUiState, mOverviewProxyService);
+ mModeSwitchesController, mSysUiState, mOverviewProxyService, mSecureSettings);
mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier(
mContext.getSystemService(DisplayManager.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
index 41fd2b3..9c601a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SecureSettingsContentObserverTest.java
@@ -18,18 +18,20 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.ActivityManager;
import android.content.Context;
-import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
/** Test for {@link SecureSettingsContentObserver}. */
@RunWith(AndroidTestingRunner.class)
@@ -40,7 +42,9 @@
@Before
public void setUpObserver() {
- mTestObserver = new FakeSecureSettingsContentObserver(mContext,
+ UserTracker userTracker = Mockito.mock(UserTracker.class);
+ Mockito.when(userTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
+ mTestObserver = new FakeSecureSettingsContentObserver(mContext, userTracker,
Settings.Secure.ACCESSIBILITY_BUTTON_MODE);
}
@@ -57,7 +61,7 @@
@Test
public void checkValue() {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 1, UserHandle.USER_CURRENT);
+ Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 1, ActivityManager.getCurrentUser());
assertThat(mTestObserver.getSettingsValue()).isEqualTo("1");
}
@@ -66,9 +70,9 @@
private static class FakeSecureSettingsContentObserver extends
SecureSettingsContentObserver<Object> {
- protected FakeSecureSettingsContentObserver(Context context,
+ protected FakeSecureSettingsContentObserver(Context context, UserTracker userTracker,
String secureSettingsKey) {
- super(context, secureSettingsKey);
+ super(context, userTracker, secureSettingsKey);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 0850330..84ea54c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -49,6 +49,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -97,6 +98,8 @@
IRemoteMagnificationAnimationCallback mAnimationCallback2;
@Mock(answer = Answers.RETURNS_SELF)
SysUiState mSysUiState;
+ @Mock
+ SecureSettings mSecureSettings;
private SpyWindowMagnificationController mController;
private WindowMagnificationController mSpyController;
private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
@@ -121,7 +124,7 @@
mController = new SpyWindowMagnificationController(mContext, mHandler,
mWindowMagnificationAnimationController,
mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(),
- mWindowMagnifierCallback, mSysUiState);
+ mWindowMagnifierCallback, mSysUiState, mSecureSettings);
mSpyController = mController.getSpyController();
}
@@ -761,7 +764,8 @@
WindowMagnificationAnimationController animationController,
SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction,
- WindowMagnifierCallback callback, SysUiState sysUiState) {
+ WindowMagnifierCallback callback, SysUiState sysUiState,
+ SecureSettings secureSettings) {
super(
context,
handler,
@@ -771,7 +775,8 @@
transaction,
callback,
sysUiState,
- WindowManagerGlobal::getWindowSession);
+ WindowManagerGlobal::getWindowSession,
+ secureSettings);
mSpyController = Mockito.mock(WindowMagnificationController.class);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 9d39a8c..89ab835 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -34,8 +34,11 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.AdditionalAnswers.returnsSecondArg;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
@@ -85,6 +88,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.model.SysUiState;
import com.android.systemui.util.leak.ReferenceTestUtils;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.utils.os.FakeHandler;
import com.google.common.util.concurrent.AtomicDouble;
@@ -122,6 +126,8 @@
IRemoteMagnificationAnimationCallback mAnimationCallback;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ @Mock
+ private SecureSettings mSecureSettings;
private Handler mHandler;
private TestableWindowManager mWindowManager;
@@ -157,6 +163,10 @@
}).when(mSfVsyncFrameProvider).postFrameCallback(
any(FrameCallback.class));
mSysUiState.addCallback(Mockito.mock(SysUiState.SysUiStateCallback.class));
+ when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).then(
+ returnsSecondArg());
+ when(mSecureSettings.getFloatForUser(anyString(), anyFloat(), anyInt())).then(
+ returnsSecondArg());
mResources = getContext().getOrCreateTestableResources().getResources();
mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
@@ -171,7 +181,8 @@
mTransaction,
mWindowMagnifierCallback,
mSysUiState,
- () -> mWindowSessionSpy);
+ () -> mWindowSessionSpy,
+ mSecureSettings);
verify(mMirrorWindowControl).setWindowDelegate(
any(MirrorWindowControl.MirrorWindowDelegate.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
index 2f94b69..d803075 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSettingsTest.java
@@ -38,6 +38,7 @@
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -61,6 +62,8 @@
@Mock
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
@Mock
+ private SecureSettings mSecureSettings;
+ @Mock
private WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback;
private TestableWindowManager mWindowManager;
private WindowMagnificationSettings mWindowMagnificationSettings;
@@ -77,7 +80,8 @@
mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
mWindowMagnificationSettings = new WindowMagnificationSettings(mContext,
- mWindowMagnificationSettingsCallback, mSfVsyncFrameProvider);
+ mWindowMagnificationSettingsCallback, mSfVsyncFrameProvider,
+ mSecureSettings);
mSettingView = mWindowMagnificationSettings.getSettingView();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
index e1bd25b..14b00ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -46,6 +46,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -70,6 +71,8 @@
private IWindowMagnificationConnectionCallback mConnectionCallback;
@Mock
private OverviewProxyService mOverviewProxyService;
+ @Mock
+ private SecureSettings mSecureSettings;
private CommandQueue mCommandQueue;
private WindowMagnification mWindowMagnification;
@@ -90,7 +93,7 @@
mCommandQueue = new CommandQueue(getContext());
mWindowMagnification = new WindowMagnification(getContext(),
getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController,
- mSysUiState, mOverviewProxyService);
+ mSysUiState, mOverviewProxyService, mSecureSettings);
mWindowMagnification.start();
final ArgumentCaptor<OverviewProxyListener> listenerArgumentCaptor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index 77d38c5..15a3145 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.display.DisplayManager;
@@ -46,6 +47,7 @@
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -54,6 +56,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -79,9 +83,12 @@
private KeyguardUpdateMonitorCallback mKeyguardCallback;
private int mLastButtonMode;
private String mLastButtonTargets;
+ @Mock
+ private SecureSettings mSecureSettings;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mContextWrapper = new ContextWrapper(mContext) {
@Override
public Context createContextAsUser(UserHandle user, int flags) {
@@ -150,7 +157,7 @@
public void onKeyguardVisibilityChanged_showing_destroyWidget() {
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
- mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper);
+ mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserUnlocked();
@@ -176,7 +183,7 @@
final int fakeUserId = 1;
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
- mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper);
+ mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserSwitching(fakeUserId);
@@ -189,7 +196,7 @@
final int fakeUserId = 1;
enableAccessibilityFloatingMenuConfig();
mController = setUpController();
- mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper);
+ mController.mFloatingMenu = new AccessibilityFloatingMenu(mContextWrapper, mSecureSettings);
captureKeyguardUpdateMonitorCallback();
mKeyguardCallback.onUserUnlocked();
mKeyguardCallback.onKeyguardVisibilityChanged(true);
@@ -219,7 +226,7 @@
public void onAccessibilityButtonModeChanged_floatingModeAndHasButtonTargets_showWidget() {
Settings.Secure.putStringForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonModeChanged(ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
@@ -230,7 +237,7 @@
@Test
public void onAccessibilityButtonModeChanged_floatingModeAndNoButtonTargets_destroyWidget() {
Settings.Secure.putStringForUser(mContextWrapper.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, "", UserHandle.USER_CURRENT);
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, "", ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonModeChanged(ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
@@ -242,7 +249,7 @@
public void onAccessibilityButtonModeChanged_navBarModeAndHasButtonTargets_destroyWidget() {
Settings.Secure.putStringForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonModeChanged(ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
@@ -253,7 +260,7 @@
@Test
public void onAccessibilityButtonModeChanged_navBarModeAndNoButtonTargets_destroyWidget() {
Settings.Secure.putStringForUser(mContextWrapper.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, "", UserHandle.USER_CURRENT);
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, "", ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonModeChanged(ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
@@ -265,7 +272,7 @@
public void onAccessibilityButtonTargetsChanged_floatingModeAndHasButtonTargets_showWidget() {
Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonTargetsChanged(TEST_A11Y_BTN_TARGETS);
@@ -277,7 +284,7 @@
public void onAccessibilityButtonTargetsChanged_floatingModeAndNoButtonTargets_destroyWidget() {
Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonTargetsChanged("");
@@ -289,7 +296,7 @@
public void onAccessibilityButtonTargetsChanged_navBarModeAndHasButtonTargets_destroyWidget() {
Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
- ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, UserHandle.USER_CURRENT);
+ ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonTargetsChanged(TEST_A11Y_BTN_TARGETS);
@@ -301,7 +308,7 @@
public void onAccessibilityButtonTargetsChanged_navBarModeAndNoButtonTargets_destroyWidget() {
Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE,
- ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, UserHandle.USER_CURRENT);
+ ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR, ActivityManager.getCurrentUser());
mController = setUpController();
mController.onAccessibilityButtonTargetsChanged("");
@@ -352,7 +359,7 @@
final AccessibilityFloatingMenuController controller =
new AccessibilityFloatingMenuController(mContextWrapper, windowManager,
displayManager, mAccessibilityManager, mTargetsObserver, mModeObserver,
- mKeyguardUpdateMonitor, featureFlags);
+ mKeyguardUpdateMonitor, featureFlags, mSecureSettings);
controller.init();
return controller;
@@ -361,10 +368,10 @@
private void enableAccessibilityFloatingMenuConfig() {
Settings.Secure.putIntForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_MODE, ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
Settings.Secure.putStringForUser(mContextWrapper.getContentResolver(),
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, TEST_A11Y_BTN_TARGETS,
- UserHandle.USER_CURRENT);
+ ActivityManager.getCurrentUser());
}
private void captureKeyguardUpdateMonitorCallback() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java
index 558261b..04345fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java
@@ -31,6 +31,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -55,6 +56,8 @@
@Mock
private AccessibilityManager mAccessibilityManager;
+ @Mock
+ private SecureSettings mSecureSettings;
private AccessibilityFloatingMenuView mMenuView;
private AccessibilityFloatingMenu mMenu;
@@ -69,7 +72,7 @@
final Position position = new Position(0, 0);
mMenuView = new AccessibilityFloatingMenuView(mContext, position);
- mMenu = new AccessibilityFloatingMenu(mContext, mMenuView);
+ mMenu = new AccessibilityFloatingMenu(mContext, mSecureSettings, mMenuView);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java
index a4b9b08..f6ca938 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DismissAnimationControllerTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.accessibility.floatingmenu;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -27,6 +28,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.bubbles.DismissView;
import org.junit.Before;
@@ -54,7 +56,8 @@
@Before
public void setUp() throws Exception {
final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class);
- final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager);
+ final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
+ mock(SecureSettings.class));
final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext,
stubWindowManager);
final MenuView stubMenuView = new MenuView(mContext, stubMenuViewModel,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
index 7356184..3a8bcd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuAnimationControllerTest.java
@@ -41,6 +41,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -77,7 +78,8 @@
final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class);
final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext,
stubWindowManager);
- final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager);
+ final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
+ mock(SecureSettings.class));
mMenuView = spy(new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance));
mViewPropertyAnimator = spy(mMenuView.animate());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java
index 06340af..1faa8ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuInfoRepositoryTest.java
@@ -31,6 +31,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -57,6 +58,8 @@
@Mock
private MenuInfoRepository.OnSettingsContentsChanged mMockSettingsContentsChanged;
+ @Mock
+ private SecureSettings mSecureSettings;
private MenuInfoRepository mMenuInfoRepository;
private final List<String> mShortcutTargets = new ArrayList<>();
@@ -69,7 +72,7 @@
anyInt());
mMenuInfoRepository = new MenuInfoRepository(mContext, mAccessibilityManager,
- mMockSettingsContentsChanged);
+ mMockSettingsContentsChanged, mSecureSettings);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
index f17b1cf..1b0a10e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuItemAccessibilityDelegateTest.java
@@ -39,6 +39,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Rule;
@@ -58,7 +59,8 @@
@Mock
private AccessibilityManager mAccessibilityManager;
-
+ @Mock
+ private SecureSettings mSecureSettings;
@Mock
private DismissAnimationController.DismissCallback mStubDismissCallback;
@@ -73,7 +75,8 @@
final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class);
final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext,
stubWindowManager);
- final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager);
+ final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
+ mSecureSettings);
final int halfScreenHeight =
stubWindowManager.getCurrentWindowMetrics().getBounds().height() / 2;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java
index ed9562d..d4efbe4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuListViewTouchHandlerTest.java
@@ -39,6 +39,7 @@
import com.android.internal.accessibility.dialog.AccessibilityTarget;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.MotionEventHelper;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.bubbles.DismissView;
import org.junit.After;
@@ -78,7 +79,8 @@
@Before
public void setUp() throws Exception {
final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
- final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager);
+ final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
+ mock(SecureSettings.class));
final MenuViewAppearance stubMenuViewAppearance = new MenuViewAppearance(mContext,
windowManager);
mStubMenuView = new MenuView(mContext, stubMenuViewModel, stubMenuViewAppearance);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
index dd7ce0e..31824ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerControllerTest.java
@@ -39,6 +39,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Rule;
@@ -63,6 +64,9 @@
private AccessibilityManager mAccessibilityManager;
@Mock
+ private SecureSettings mSecureSettings;
+
+ @Mock
private WindowMetrics mWindowMetrics;
private MenuViewLayerController mMenuViewLayerController;
@@ -77,7 +81,7 @@
when(mWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, 1080, 2340));
when(mWindowMetrics.getWindowInsets()).thenReturn(stubDisplayInsets());
mMenuViewLayerController = new MenuViewLayerController(mContext, mWindowManager,
- mAccessibilityManager);
+ mAccessibilityManager, mSecureSettings);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
index 428a00a..728ea1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java
@@ -22,7 +22,6 @@
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
-import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.android.systemui.accessibility.floatingmenu.MenuViewLayer.LayerIndex;
import static com.google.common.truth.Truth.assertThat;
@@ -54,6 +53,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -100,6 +100,9 @@
private IAccessibilityFloatingMenu mFloatingMenu;
@Mock
+ private SecureSettings mSecureSettings;
+
+ @Mock
private WindowManager mStubWindowManager;
@Mock
@@ -114,7 +117,7 @@
doReturn(mWindowMetrics).when(mStubWindowManager).getCurrentWindowMetrics();
mMenuViewLayer = new MenuViewLayer(mContext, mStubWindowManager, mStubAccessibilityManager,
- mFloatingMenu);
+ mFloatingMenu, mSecureSettings);
mMenuView = (MenuView) mMenuViewLayer.getChildAt(LayerIndex.MENU_VIEW);
mMenuAnimationController = mMenuView.getMenuAnimationController();
@@ -170,16 +173,10 @@
@Test
public void tiggerDismissMenuAction_matchA11yButtonTargetsResult() {
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
- MAGNIFICATION_COMPONENT_NAME.flattenToString(), UserHandle.USER_CURRENT);
-
mMenuViewLayer.mDismissMenuAction.run();
- final String value =
- Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, UserHandle.USER_CURRENT);
-
- assertThat(value).isEqualTo("");
+ verify(mSecureSettings).putStringForUser(
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, /* value= */ "",
+ UserHandle.USER_CURRENT);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
index 5a1a6db..5cd0fd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -35,6 +36,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -68,7 +70,8 @@
mUiModeManager = mContext.getSystemService(UiModeManager.class);
mNightMode = mUiModeManager.getNightMode();
mUiModeManager.setNightMode(MODE_NIGHT_YES);
- final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager);
+ final MenuViewModel stubMenuViewModel = new MenuViewModel(mContext, mAccessibilityManager,
+ mock(SecureSettings.class));
final WindowManager stubWindowManager = mContext.getSystemService(WindowManager.class);
mStubMenuViewAppearance = new MenuViewAppearance(mContext, stubWindowManager);
mMenuView = spy(new MenuView(mContext, stubMenuViewModel, mStubMenuViewAppearance));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index 3c40835..b92c5d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -53,6 +53,7 @@
import com.airbnb.lottie.LottieAnimationView
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
import com.android.systemui.dump.DumpManager
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.FakeExecutor
@@ -106,8 +107,7 @@
enum class DeviceConfig {
X_ALIGNED,
- Y_ALIGNED_UNFOLDED,
- Y_ALIGNED_FOLDED
+ Y_ALIGNED,
}
private lateinit var deviceConfig: DeviceConfig
@@ -143,6 +143,7 @@
private fun testWithDisplay(
deviceConfig: DeviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation: Boolean = false,
initInfo: DisplayInfo.() -> Unit = {},
windowInsets: WindowInsets = insetsForSmallNavbar(),
block: () -> Unit
@@ -151,27 +152,21 @@
when (deviceConfig) {
DeviceConfig.X_ALIGNED -> {
- displayWidth = 2560
- displayHeight = 1600
- sensorLocation = SensorLocationInternal("", 2325, 0, 0)
- boundsWidth = 160
- boundsHeight = 84
+ displayWidth = 3000
+ displayHeight = 1500
+ sensorLocation = SensorLocationInternal("", 2500, 0, 0)
+ boundsWidth = 200
+ boundsHeight = 100
}
- DeviceConfig.Y_ALIGNED_UNFOLDED -> {
- displayWidth = 2208
- displayHeight = 1840
- sensorLocation = SensorLocationInternal("", 0, 510, 0)
- boundsWidth = 110
- boundsHeight = 210
- }
- DeviceConfig.Y_ALIGNED_FOLDED -> {
- displayWidth = 1080
- displayHeight = 2100
- sensorLocation = SensorLocationInternal("", 0, 590, 0)
- boundsWidth = 110
- boundsHeight = 210
+ DeviceConfig.Y_ALIGNED -> {
+ displayWidth = 2500
+ displayHeight = 2000
+ sensorLocation = SensorLocationInternal("", 0, 300, 0)
+ boundsWidth = 100
+ boundsHeight = 200
}
}
+
indicatorBounds = Rect(0, 0, boundsWidth, boundsHeight)
displayBounds = Rect(0, 0, displayWidth, displayHeight)
var locations = listOf(sensorLocation)
@@ -194,8 +189,10 @@
val displayInfo = DisplayInfo()
displayInfo.initInfo()
+
val dmGlobal = mock(DisplayManagerGlobal::class.java)
val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
+
whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
whenEver(windowManager.defaultDisplay).thenReturn(display)
whenEver(windowManager.maximumWindowMetrics)
@@ -203,9 +200,15 @@
whenEver(windowManager.currentWindowMetrics)
.thenReturn(WindowMetrics(displayBounds, windowInsets))
+ val sideFpsControllerContext = context.createDisplayContext(display) as SysuiTestableContext
+ sideFpsControllerContext.orCreateTestableResources.addOverride(
+ com.android.internal.R.bool.config_reverseDefaultRotation,
+ isReverseDefaultRotation
+ )
+
sideFpsController =
SideFpsController(
- context.createDisplayContext(display),
+ sideFpsControllerContext,
layoutInflater,
fingerprintManager,
windowManager,
@@ -299,108 +302,316 @@
}
@Test
- fun showsWithTaskbar() =
- testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_0 }) {
- hidesWithTaskbar(visible = true)
- }
-
- @Test
- fun showsWithTaskbarOnY() =
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_0() =
testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_0 }
- ) { hidesWithTaskbar(visible = true) }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
@Test
- fun showsWithTaskbar90() =
- testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED, { rotation = Surface.ROTATION_90 }) {
- hidesWithTaskbar(visible = true)
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 },
+ windowInsets = insetsForSmallNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 },
+ windowInsets = insetsForLargeNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_270 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_0 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_90 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_90 },
+ windowInsets = insetsForSmallNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_90 },
+ windowInsets = insetsForLargeNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_180 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_270 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_0 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_90 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_180 },
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
}
@Test
- fun showsWithTaskbar90OnY() =
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_270() =
testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
- { rotation = Surface.ROTATION_90 }
- ) { hidesWithTaskbar(visible = true) }
-
- @Test
- fun showsWithTaskbar180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- { rotation = Surface.ROTATION_180 }
- ) { hidesWithTaskbar(visible = true) }
-
- @Test
- fun showsWithTaskbar270OnY() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 }
- ) { hidesWithTaskbar(visible = true) }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
@Test
- fun showsWithTaskbarCollapsedDown() =
+ fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForSmallNavbar()
- ) { hidesWithTaskbar(visible = true) }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
@Test
- fun showsWithTaskbarCollapsedDownOnY() =
+ fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForSmallNavbar()
- ) { hidesWithTaskbar(visible = true) }
-
- @Test
- fun hidesWithTaskbarDown() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForLargeNavbar()
- ) { hidesWithTaskbar(visible = false) }
-
- @Test
- fun hidesWithTaskbarDownOnY() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED,
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
{ rotation = Surface.ROTATION_270 },
windowInsets = insetsForLargeNavbar()
- ) { hidesWithTaskbar(visible = true) }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
- private fun hidesWithTaskbar(visible: Boolean) {
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_0 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_90 },
+ ) {
+ verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+ }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_180 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_180 },
+ windowInsets = insetsForSmallNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ @Test
+ fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_180 },
+ windowInsets = insetsForLargeNavbar()
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+
+ @Test
+ fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_270 }
+ ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+
+ private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
+ sideFpsController.overlayOffsets = sensorLocation
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
- sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(visible, false)
+ sideFpsController.overviewProxyListener.onTaskbarStatusUpdated(true, false)
executor.runAllReady()
verify(windowManager).addView(any(), any())
verify(windowManager, never()).removeView(any())
- verify(sideFpsView).visibility = if (visible) View.VISIBLE else View.GONE
+ verify(sideFpsView).visibility = if (sfpsViewVisible) View.VISIBLE else View.GONE
}
+ /**
+ * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
+ * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
+ * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
+ * in other rotations have been omitted.
+ */
@Test
- fun testIndicatorPlacementForXAlignedSensor() =
- testWithDisplay(deviceConfig = DeviceConfig.X_ALIGNED) {
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ fun verifiesIndicatorPlacementForXAlignedSensor_0() {
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_0 }
+ ) {
sideFpsController.overlayOffsets = sensorLocation
+
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
+
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
}
+ }
+ /**
+ * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
+ * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
+ * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
+ * correctly, tests for indicator placement in other rotations have been omitted.
+ */
@Test
- fun testIndicatorPlacementForYAlignedSensor() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
+ fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() {
+ testWithDisplay(
+ deviceConfig = DeviceConfig.X_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_270 }
+ ) {
sideFpsController.overlayOffsets = sensorLocation
+
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
+
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ executor.runAllReady()
+
+ verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
+ assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
+ assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
+ }
+ }
+
+ /**
+ * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
+ * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
+ * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
+ * in other rotations have been omitted.
+ */
+ @Test
+ fun verifiesIndicatorPlacementForYAlignedSensor_0() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = false,
+ { rotation = Surface.ROTATION_0 }
+ ) {
+ sideFpsController.overlayOffsets = sensorLocation
+
+ sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
+
+ overlayController.show(SENSOR_ID, REASON_UNKNOWN)
+ executor.runAllReady()
+
+ verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
+ assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
+ assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
+ }
+
+ /**
+ * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
+ * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
+ * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
+ * correctly, tests for indicator placement in other rotations have been omitted.
+ */
+ @Test
+ fun verifiesIndicatorPlacementForYAlignedSensor_InReverseDefaultRotation_270() =
+ testWithDisplay(
+ deviceConfig = DeviceConfig.Y_ALIGNED,
+ isReverseDefaultRotation = true,
+ { rotation = Surface.ROTATION_270 }
+ ) {
+ sideFpsController.overlayOffsets = sensorLocation
+
+ sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
+
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
@@ -412,7 +623,6 @@
@Test
fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
// By default all those tests assume the side fps sensor is available.
-
assertThat(fingerprintManager.hasSideFpsSensor()).isTrue()
}
@@ -425,7 +635,7 @@
@Test
fun testLayoutParams_isKeyguardDialogType() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
+ testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
sideFpsController.overlayOffsets = sensorLocation
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
@@ -440,7 +650,7 @@
@Test
fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
+ testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
sideFpsController.overlayOffsets = sensorLocation
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
@@ -455,7 +665,7 @@
@Test
fun testLayoutParams_hasTrustedOverlayWindowFlag() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED_UNFOLDED) {
+ testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
sideFpsController.overlayOffsets = sensorLocation
sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 7c9d22f..b9a952a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -53,6 +53,7 @@
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.settings.SecureSettings
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
@@ -99,6 +100,7 @@
@Mock private lateinit var unlockedScreenOffAnimationController:
UnlockedScreenOffAnimationController
@Mock private lateinit var udfpsDisplayMode: UdfpsDisplayModeProvider
+ @Mock private lateinit var secureSettings: SecureSettings
@Mock private lateinit var controllerCallback: IUdfpsOverlayControllerCallback
@Mock private lateinit var udfpsController: UdfpsController
@Mock private lateinit var udfpsView: UdfpsView
@@ -138,10 +140,10 @@
context, fingerprintManager, inflater, windowManager, accessibilityManager,
statusBarStateController, shadeExpansionStateManager, statusBarKeyguardViewManager,
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
- configurationController, keyguardStateController,
- unlockedScreenOffAnimationController, udfpsDisplayMode, REQUEST_ID, reason,
+ configurationController, keyguardStateController, unlockedScreenOffAnimationController,
+ udfpsDisplayMode, secureSettings, REQUEST_ID, reason,
controllerCallback, onTouch, activityLaunchAnimator, featureFlags,
- primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable,
+ primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable
)
block()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index d7b7a7d..dd7082a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -98,6 +98,7 @@
import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.concurrency.FakeExecution;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.util.time.SystemClock;
@@ -209,6 +210,8 @@
private SessionTracker mSessionTracker;
@Mock
private AlternateBouncerInteractor mAlternateBouncerInteractor;
+ @Mock
+ private SecureSettings mSecureSettings;
// Capture listeners so that they can be used to send events
@Captor
@@ -302,7 +305,7 @@
mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker,
mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor,
mPrimaryBouncerInteractor, mSinglePointerTouchProcessor, mSessionTracker,
- mAlternateBouncerInteractor);
+ mAlternateBouncerInteractor, mSecureSettings);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
index 262b4b8..80c3e5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.ActivityIntentHelper
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -69,6 +70,8 @@
lateinit var cameraIntents: CameraIntentsWrapper
@Mock
lateinit var contentResolver: ContentResolver
+ @Mock
+ lateinit var userTracker: UserTracker
private lateinit var underTest: CameraGestureHelper
@@ -96,6 +99,7 @@
cameraIntents = cameraIntents,
contentResolver = contentResolver,
uiExecutor = MoreExecutors.directExecutor(),
+ userTracker = userTracker,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 5c2b153..af027e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.hardware.display.AmbientDisplayConfiguration;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -36,6 +37,7 @@
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.doze.DozeMachine.State;
+import com.android.systemui.settings.UserTracker;
import org.junit.Before;
import org.junit.Test;
@@ -48,6 +50,7 @@
@RunWithLooper
public class DozeDockHandlerTest extends SysuiTestCase {
@Mock private DozeMachine mMachine;
+ @Mock private UserTracker mUserTracker;
private AmbientDisplayConfiguration mConfig;
private DockManagerFake mDockManagerFake;
private DozeDockHandler mDockHandler;
@@ -57,9 +60,10 @@
MockitoAnnotations.initMocks(this);
mConfig = DozeConfigurationUtil.createMockConfig();
mDockManagerFake = spy(new DockManagerFake());
- mDockHandler = new DozeDockHandler(mConfig, mDockManagerFake);
+ mDockHandler = new DozeDockHandler(mConfig, mDockManagerFake, mUserTracker);
mDockHandler.setDozeMachine(mMachine);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
when(mMachine.getState()).thenReturn(State.DOZE_AOD);
doReturn(true).when(mConfig).alwaysOnEnabled(anyInt());
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 5bbd810..a636b7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -45,6 +45,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.res.Configuration;
import android.hardware.display.AmbientDisplayConfiguration;
import android.testing.AndroidTestingRunner;
@@ -57,6 +58,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -85,6 +87,8 @@
private DozeMachine.Part mPartMock;
@Mock
private DozeMachine.Part mAnotherPartMock;
+ @Mock
+ private UserTracker mUserTracker;
private DozeServiceFake mServiceFake;
private WakeLockFake mWakeLockFake;
private AmbientDisplayConfiguration mAmbientDisplayConfigMock;
@@ -97,6 +101,7 @@
mAmbientDisplayConfigMock = mock(AmbientDisplayConfiguration.class);
when(mDockManager.isDocked()).thenReturn(false);
when(mDockManager.isHidden()).thenReturn(false);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
mMachine = new DozeMachine(mServiceFake,
mAmbientDisplayConfigMock,
@@ -105,7 +110,8 @@
mDozeLog,
mDockManager,
mHost,
- new DozeMachine.Part[]{mPartMock, mAnotherPartMock});
+ new DozeMachine.Part[]{mPartMock, mAnotherPartMock},
+ mUserTracker);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 03827da..3af444a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -34,6 +34,7 @@
import static org.junit.Assert.assertNotSame;
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.doAnswer;
import static org.mockito.Mockito.reset;
@@ -57,6 +58,7 @@
import com.android.systemui.util.concurrency.FakeThreadFactory;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.FakeSensorManager;
+import com.android.systemui.util.settings.SystemSettings;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -94,6 +96,8 @@
DevicePostureController mDevicePostureController;
@Mock
DozeLog mDozeLog;
+ @Mock
+ SystemSettings mSystemSettings;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
@@ -102,9 +106,8 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, DEFAULT_BRIGHTNESS,
- UserHandle.USER_CURRENT);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
+ eq(UserHandle.USER_CURRENT))).thenReturn(DEFAULT_BRIGHTNESS);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
@@ -131,7 +134,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
}
@Test
@@ -157,11 +161,10 @@
}
@Test
- public void testAod_usesLightSensorRespectingUserSetting() throws Exception {
+ public void testAod_usesLightSensorRespectingUserSetting() {
int maxBrightness = 3;
- Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, maxBrightness,
- UserHandle.USER_CURRENT);
+ when(mSystemSettings.getIntForUser(eq(Settings.System.SCREEN_BRIGHTNESS), anyInt(),
+ eq(UserHandle.USER_CURRENT))).thenReturn(maxBrightness);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
assertEquals(maxBrightness, mServiceFake.screenBrightness);
@@ -238,7 +241,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
reset(mDozeHost);
@@ -275,7 +279,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -306,7 +311,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
// GIVEN the device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -344,7 +350,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -386,7 +393,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mSystemSettings);
verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
// GIVEN device is in AOD
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index b6da649..a88a8e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -37,11 +37,11 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.display.AmbientDisplayConfiguration;
-import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -122,11 +122,13 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
when(mAmbientDisplayConfiguration.tapSensorTypeMapping())
.thenReturn(new String[]{"tapSensor"});
when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
- when(mAmbientDisplayConfiguration.enabled(UserHandle.USER_CURRENT)).thenReturn(true);
+ when(mAmbientDisplayConfiguration.enabled(ActivityManager.getCurrentUser())).thenReturn(
+ true);
doAnswer(invocation -> {
((Runnable) invocation.getArgument(0)).run();
return null;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
index 32b9945..9064470 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
@@ -36,6 +36,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.hardware.display.AmbientDisplayConfiguration;
import android.testing.AndroidTestingRunner;
import android.testing.UiThreadTest;
@@ -43,6 +44,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import org.junit.After;
@@ -73,6 +75,8 @@
private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@Mock
private BiometricUnlockController mBiometricUnlockController;
+ @Mock
+ private UserTracker mUserTracker;
@Mock
private DozeMachine mDozeMachine;
@@ -89,12 +93,14 @@
when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController);
when(mBiometricUnlockController.hasPendingAuthentication()).thenReturn(false);
when(mDozeHost.isProvisioned()).thenReturn(true);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
mDozeSuppressor = new DozeSuppressor(
mDozeHost,
mConfig,
mDozeLog,
- mBiometricUnlockControllerLazy);
+ mBiometricUnlockControllerLazy,
+ mUserTracker);
mDozeSuppressor.setDozeMachine(mDozeMachine);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 8f97026..b73bfc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -275,6 +275,32 @@
}
@Test
+ public void testOnEndDream() throws RemoteException {
+ final IBinder proxy = mService.onBind(new Intent());
+ final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
+
+ // Inform the overlay service of dream starting.
+ overlay.startDream(mWindowParams, mDreamOverlayCallback,
+ LOW_LIGHT_COMPONENT.flattenToString(), false /*shouldShowComplication*/);
+ mMainExecutor.runAllReady();
+
+ // Verify view added.
+ verify(mWindowManager).addView(mViewCaptor.capture(), any());
+
+ // Service destroyed.
+ mService.onEndDream();
+ mMainExecutor.runAllReady();
+
+ // Verify view removed.
+ verify(mWindowManager).removeView(mViewCaptor.getValue());
+
+ // Verify state correctly set.
+ verify(mStateController).setOverlayActive(false);
+ verify(mStateController).setLowLightActive(false);
+ verify(mStateController).setEntryAnimationsFinished(false);
+ }
+
+ @Test
public void testDestroy() throws RemoteException {
final IBinder proxy = mService.onBind(new Intent());
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 85c2819..596b903 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -31,6 +31,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.Context;
import android.content.res.Resources;
@@ -47,6 +48,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -109,6 +111,8 @@
View mStatusBarItemView;
@Mock
DreamOverlayStateController mDreamOverlayStateController;
+ @Mock
+ UserTracker mUserTracker;
@Captor
private ArgumentCaptor<DreamOverlayStateController.Callback> mCallbackCaptor;
@@ -125,6 +129,7 @@
.thenReturn(NOTIFICATION_INDICATOR_FORMATTER_STRING);
doCallRealMethod().when(mView).setVisibility(anyInt());
doCallRealMethod().when(mView).getVisibility();
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
mController = new DreamOverlayStatusBarViewController(
mView,
@@ -140,7 +145,8 @@
mZenModeController,
mStatusBarWindowStateController,
mDreamOverlayStatusBarItemsProvider,
- mDreamOverlayStateController);
+ mDreamOverlayStateController,
+ mUserTracker);
}
@Test
@@ -282,7 +288,8 @@
mZenModeController,
mStatusBarWindowStateController,
mDreamOverlayStatusBarItemsProvider,
- mDreamOverlayStateController);
+ mDreamOverlayStateController,
+ mUserTracker);
controller.onViewAttached();
verify(mView, never()).showIcon(
eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
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 c8a352d..8795ac0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -558,8 +558,8 @@
UserInfo currentUser = mockCurrentUser(FLAG_ADMIN);
when(mGlobalActionsDialogLite.getCurrentUser()).thenReturn(currentUser);
- doReturn(1).when(mGlobalSettings)
- .getIntForUser(Settings.Global.BUGREPORT_IN_POWER_MENU, 0, currentUser.id);
+ when(mGlobalSettings.getIntForUser(Settings.Secure.BUGREPORT_IN_POWER_MENU,
+ 0, currentUser.id)).thenReturn(1);
GlobalActionsDialogLite.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
@@ -572,7 +572,7 @@
when(mGlobalActionsDialogLite.getCurrentUser()).thenReturn(currentUser);
doReturn(1).when(mGlobalSettings)
- .getIntForUser(Settings.Global.BUGREPORT_IN_POWER_MENU, 0, currentUser.id);
+ .getIntForUser(Settings.Secure.BUGREPORT_IN_POWER_MENU, 0, currentUser.id);
GlobalActionsDialogLite.BugReportAction bugReportAction =
mGlobalActionsDialogLite.makeBugReportActionForTesting();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index e9db8cc..b9cfc65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.ActivityManager;
@@ -35,12 +36,12 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.UserHandle;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -71,6 +72,7 @@
private @Mock Context mContext;
private @Mock TaskStackChangeListeners mTaskStackChangeListeners;
private @Mock IActivityTaskManager mIActivityTaskManager;
+ private @Mock UserTracker mUserTracker;
private WorkLockActivityController mController;
private TaskStackChangeListener mTaskStackListener;
@@ -81,12 +83,13 @@
// Set a package name to use for checking ComponentName well-formedness in tests.
doReturn("com.example.test").when(mContext).getPackageName();
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
// Construct controller. Save the TaskStackListener for injecting events.
final ArgumentCaptor<TaskStackChangeListener> listenerCaptor =
ArgumentCaptor.forClass(TaskStackChangeListener.class);
- mController = new WorkLockActivityController(mContext, mTaskStackChangeListeners,
- mIActivityTaskManager);
+ mController = new WorkLockActivityController(mContext, mUserTracker,
+ mTaskStackChangeListeners, mIActivityTaskManager);
verify(mTaskStackChangeListeners).registerTaskStackListener(listenerCaptor.capture());
mTaskStackListener = listenerCaptor.getValue();
@@ -135,7 +138,7 @@
anyInt(),
eq((ProfilerInfo) null),
argThat(hasOptions(taskId, taskOverlay)),
- eq(UserHandle.USER_CURRENT));
+ eq(ActivityManager.getCurrentUser()));
}
private void verifyStartActivity(int taskId, boolean taskOverlay) throws Exception {
@@ -151,7 +154,7 @@
anyInt(),
eq((ProfilerInfo) null),
argThat(hasOptions(taskId, taskOverlay)),
- eq(UserHandle.USER_CURRENT));
+ eq(ActivityManager.getCurrentUser()));
}
private static ArgumentMatcher<Intent> hasComponent(final Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
index 7205f30..8da4eae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -22,15 +22,21 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraGestureHelper
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
+import org.mockito.Mockito.anyInt
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class CameraQuickAffordanceConfigTest : SysuiTestCase() {
@@ -62,4 +68,24 @@
.launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
}
+
+ @Test
+ fun `getPickerScreenState - default when launchable`() = runTest {
+ setLaunchable(true)
+
+ Truth.assertThat(underTest.getPickerScreenState())
+ .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
+ }
+
+ @Test
+ fun `getPickerScreenState - unavailable when not launchable`() = runTest {
+ setLaunchable(false)
+
+ Truth.assertThat(underTest.getPickerScreenState())
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
+ }
+
+ private fun setLaunchable(isLaunchable: Boolean) {
+ whenever(cameraGestureHelper.canCameraGestureBeLaunched(anyInt())).thenReturn(isLaunchable)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index ca44fa18..8f56b95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -114,20 +114,8 @@
}
@Test
- fun `affordance - missing icon - model is none`() = runBlockingTest {
- setUpState(hasWalletIcon = false)
- var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
-
- val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
-
- assertThat(latest).isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
-
- job.cancel()
- }
-
- @Test
fun `affordance - no selected card - model is none`() = runBlockingTest {
- setUpState(hasWalletIcon = false)
+ setUpState(hasSelectedCard = false)
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
@@ -165,7 +153,7 @@
@Test
fun `getPickerScreenState - unavailable`() = runTest {
setUpState(
- isWalletEnabled = false,
+ isWalletServiceAvailable = false,
)
assertThat(underTest.getPickerScreenState())
@@ -173,9 +161,9 @@
}
@Test
- fun `getPickerScreenState - disabled when there is no icon`() = runTest {
+ fun `getPickerScreenState - disabled when the feature is not enabled`() = runTest {
setUpState(
- hasWalletIcon = false,
+ isWalletEnabled = false,
)
assertThat(underTest.getPickerScreenState())
@@ -194,20 +182,16 @@
private fun setUpState(
isWalletEnabled: Boolean = true,
+ isWalletServiceAvailable: Boolean = true,
isWalletQuerySuccessful: Boolean = true,
- hasWalletIcon: Boolean = true,
hasSelectedCard: Boolean = true,
) {
whenever(walletController.isWalletEnabled).thenReturn(isWalletEnabled)
val walletClient: QuickAccessWalletClient = mock()
- val icon: Drawable? =
- if (hasWalletIcon) {
- ICON
- } else {
- null
- }
- whenever(walletClient.tileIcon).thenReturn(icon)
+ whenever(walletClient.tileIcon).thenReturn(ICON)
+ whenever(walletClient.isWalletServiceAvailable).thenReturn(isWalletServiceAvailable)
+
whenever(walletController.walletClient).thenReturn(walletClient)
whenever(walletController.queryWalletCards(any())).thenAnswer { invocation ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
new file mode 100644
index 0000000..805dcec
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/VideoCameraQuickAffordanceConfigTest.kt
@@ -0,0 +1,115 @@
+/*
+ * 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.keyguard.data.quickaffordance
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.camera.CameraIntentsWrapper
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class VideoCameraQuickAffordanceConfigTest : SysuiTestCase() {
+
+ @Mock private lateinit var activityIntentHelper: ActivityIntentHelper
+
+ private lateinit var underTest: VideoCameraQuickAffordanceConfig
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest =
+ VideoCameraQuickAffordanceConfig(
+ context = context,
+ cameraIntents = CameraIntentsWrapper(context),
+ activityIntentHelper = activityIntentHelper,
+ userTracker = FakeUserTracker(),
+ )
+ }
+
+ @Test
+ fun `lockScreenState - visible when launchable`() = runTest {
+ setLaunchable(true)
+
+ val lockScreenState = collectLastValue(underTest.lockScreenState)
+
+ assertThat(lockScreenState())
+ .isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java)
+ }
+
+ @Test
+ fun `lockScreenState - hidden when not launchable`() = runTest {
+ setLaunchable(false)
+
+ val lockScreenState = collectLastValue(underTest.lockScreenState)
+
+ assertThat(lockScreenState())
+ .isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
+ }
+
+ @Test
+ fun `getPickerScreenState - default when launchable`() = runTest {
+ setLaunchable(true)
+
+ assertThat(underTest.getPickerScreenState())
+ .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java)
+ }
+
+ @Test
+ fun `getPickerScreenState - unavailable when not launchable`() = runTest {
+ setLaunchable(false)
+
+ assertThat(underTest.getPickerScreenState())
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
+ }
+
+ private fun setLaunchable(isLaunchable: Boolean) {
+ whenever(
+ activityIntentHelper.getTargetActivityInfo(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
+ .thenReturn(
+ if (isLaunchable) {
+ mock()
+ } else {
+ null
+ }
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
new file mode 100644
index 0000000..c4ae2db
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.hardware.biometrics.BiometricSourceType
+import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Captor private lateinit var callbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback>
+
+ private lateinit var testScope: TestScope
+
+ private lateinit var underTest: DeviceEntryFingerprintAuthRepository
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+
+ underTest = DeviceEntryFingerprintAuthRepositoryImpl(keyguardUpdateMonitor)
+ }
+
+ @After
+ fun tearDown() {
+ verify(keyguardUpdateMonitor).removeCallback(callbackCaptor.value)
+ }
+
+ @Test
+ fun isLockedOut_whenFingerprintLockoutStateChanges_emitsNewValue() =
+ testScope.runTest {
+ val isLockedOutValue = collectLastValue(underTest.isLockedOut)
+ runCurrent()
+
+ verify(keyguardUpdateMonitor).registerCallback(callbackCaptor.capture())
+ val callback = callbackCaptor.value
+ whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true)
+
+ callback.onLockedOutStateChanged(BiometricSourceType.FACE)
+ assertThat(isLockedOutValue()).isFalse()
+
+ callback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT)
+ assertThat(isLockedOutValue()).isTrue()
+
+ whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
+ callback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT)
+ assertThat(isLockedOutValue()).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
new file mode 100644
index 0000000..4b06905
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
@@ -0,0 +1,163 @@
+/*
+ * 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.keyguard.data.repository
+
+import android.app.trust.TrustManager
+import android.content.pm.UserInfo
+import androidx.test.filters.SmallTest
+import com.android.keyguard.logging.TrustRepositoryLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class TrustRepositoryTest : SysuiTestCase() {
+ @Mock private lateinit var trustManager: TrustManager
+ @Captor private lateinit var listenerCaptor: ArgumentCaptor<TrustManager.TrustListener>
+ private lateinit var userRepository: FakeUserRepository
+ private lateinit var testScope: TestScope
+ private val users = listOf(UserInfo(1, "user 1", 0), UserInfo(2, "user 1", 0))
+
+ private lateinit var underTest: TrustRepository
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testScope = TestScope()
+ userRepository = FakeUserRepository()
+ userRepository.setUserInfos(users)
+
+ val logger =
+ TrustRepositoryLogger(
+ LogBuffer("TestBuffer", 1, mock(LogcatEchoTracker::class.java), false)
+ )
+ underTest =
+ TrustRepositoryImpl(testScope.backgroundScope, userRepository, trustManager, logger)
+ }
+
+ @Test
+ fun isCurrentUserTrusted_whenTrustChanges_emitsLatestValue() =
+ testScope.runTest {
+ runCurrent()
+ verify(trustManager).registerTrustListener(listenerCaptor.capture())
+ val listener = listenerCaptor.value
+
+ val currentUserId = users[0].id
+ userRepository.setSelectedUserInfo(users[0])
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+
+ listener.onTrustChanged(true, false, currentUserId, 0, emptyList())
+ assertThat(isCurrentUserTrusted()).isTrue()
+
+ listener.onTrustChanged(false, false, currentUserId, 0, emptyList())
+
+ assertThat(isCurrentUserTrusted()).isFalse()
+ }
+
+ @Test
+ fun isCurrentUserTrusted_isFalse_byDefault() =
+ testScope.runTest {
+ runCurrent()
+
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+
+ assertThat(isCurrentUserTrusted()).isFalse()
+ }
+
+ @Test
+ fun isCurrentUserTrusted_whenTrustChangesForDifferentUser_noop() =
+ testScope.runTest {
+ runCurrent()
+ verify(trustManager).registerTrustListener(listenerCaptor.capture())
+ userRepository.setSelectedUserInfo(users[0])
+ val listener = listenerCaptor.value
+
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+ // current user is trusted.
+ listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
+ // some other user is not trusted.
+ listener.onTrustChanged(false, false, users[1].id, 0, emptyList())
+
+ assertThat(isCurrentUserTrusted()).isTrue()
+ }
+
+ @Test
+ fun isCurrentUserTrusted_whenTrustChangesForCurrentUser_emitsNewValue() =
+ testScope.runTest {
+ runCurrent()
+ verify(trustManager).registerTrustListener(listenerCaptor.capture())
+ val listener = listenerCaptor.value
+ userRepository.setSelectedUserInfo(users[0])
+
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+ listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
+ assertThat(isCurrentUserTrusted()).isTrue()
+
+ listener.onTrustChanged(false, true, users[0].id, 0, emptyList())
+ assertThat(isCurrentUserTrusted()).isFalse()
+ }
+
+ @Test
+ fun isCurrentUserTrusted_whenUserChangesWithoutRecentTrustChange_defaultsToFalse() =
+ testScope.runTest {
+ runCurrent()
+ verify(trustManager).registerTrustListener(listenerCaptor.capture())
+ val listener = listenerCaptor.value
+ userRepository.setSelectedUserInfo(users[0])
+ listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
+
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+ userRepository.setSelectedUserInfo(users[1])
+
+ assertThat(isCurrentUserTrusted()).isFalse()
+ }
+
+ @Test
+ fun isCurrentUserTrusted_trustChangesFirstBeforeUserInfoChanges_emitsCorrectValue() =
+ testScope.runTest {
+ runCurrent()
+ verify(trustManager).registerTrustListener(listenerCaptor.capture())
+ val listener = listenerCaptor.value
+ val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
+
+ listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
+ assertThat(isCurrentUserTrusted()).isFalse()
+
+ userRepository.setSelectedUserInfo(users[0])
+
+ assertThat(isCurrentUserTrusted()).isTrue()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index a1b6d47..5a7a3d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
+import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
@@ -56,6 +57,7 @@
*/
@SmallTest
@RunWith(JUnit4::class)
+@FlakyTest(bugId = 265303901)
class KeyguardTransitionScenariosTest : SysuiTestCase() {
private lateinit var testScope: TestScope
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 7c3c9d2..77daa3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.media.dialog;
+import static android.media.RouteListingPreference.Item.DISABLE_REASON_SUBSCRIPTION_REQUIRED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -57,6 +59,7 @@
private static final String TEST_DEVICE_ID_1 = "test_device_id_1";
private static final String TEST_DEVICE_ID_2 = "test_device_id_2";
private static final String TEST_SESSION_NAME = "test_session_name";
+
private static final int TEST_MAX_VOLUME = 20;
private static final int TEST_CURRENT_VOLUME = 10;
@@ -78,6 +81,7 @@
@Before
public void setUp() {
when(mMediaOutputController.isAdvancedLayoutSupported()).thenReturn(false);
+ when(mMediaOutputController.isSubStatusSupported()).thenReturn(false);
when(mMediaOutputController.getMediaItemList()).thenReturn(mMediaItems);
when(mMediaOutputController.getMediaDevices()).thenReturn(mMediaDevices);
when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(false);
@@ -404,6 +408,25 @@
}
@Test
+ public void subStatusSupported_onBindViewHolder_bindFailedStateDevice_verifyView() {
+ String deviceStatus = (String) mContext.getText(
+ R.string.media_output_status_require_premium);
+ when(mMediaOutputController.isSubStatusSupported()).thenReturn(true);
+ when(mMediaDevice2.hasDisabledReason()).thenReturn(true);
+ when(mMediaDevice2.getDisableReason()).thenReturn(DISABLE_REASON_SUBSCRIPTION_REQUIRED);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
+
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(deviceStatus);
+ assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
+ }
+
+ @Test
public void onBindViewHolder_inTransferring_bindTransferringDevice_verifyView() {
when(mMediaOutputController.isAnyDeviceTransferring()).thenReturn(true);
when(mMediaDevice1.getState()).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
index f5b3959..54d4460 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderCoordinatorTest.kt
@@ -45,13 +45,18 @@
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.temporarydisplay.TemporaryViewDisplayController
import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo
import com.android.systemui.temporarydisplay.chipbar.ChipbarLogger
import com.android.systemui.temporarydisplay.chipbar.FakeChipbarCoordinator
+import com.android.systemui.temporarydisplay.chipbar.SwipeChipbarAwayGestureHandler
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.view.ViewUtil
import com.android.systemui.util.wakelock.WakeLockFake
@@ -61,6 +66,7 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
+import org.mockito.Mockito.atLeast
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
@@ -93,6 +99,7 @@
@Mock private lateinit var viewUtil: ViewUtil
@Mock private lateinit var windowManager: WindowManager
@Mock private lateinit var vibratorHelper: VibratorHelper
+ @Mock private lateinit var swipeHandler: SwipeChipbarAwayGestureHandler
private lateinit var fakeWakeLockBuilder: WakeLockFake.Builder
private lateinit var fakeWakeLock: WakeLockFake
private lateinit var chipbarCoordinator: ChipbarCoordinator
@@ -143,6 +150,7 @@
powerManager,
falsingManager,
falsingCollector,
+ swipeHandler,
viewUtil,
vibratorHelper,
fakeWakeLockBuilder,
@@ -161,9 +169,7 @@
)
underTest.start()
- val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
- verify(commandQueue).addCallback(callbackCaptor.capture())
- commandQueueCallback = callbackCaptor.value!!
+ setCommandQueueCallback()
}
@Test
@@ -920,6 +926,172 @@
verify(windowManager).removeView(any())
}
+ @Test
+ fun newState_viewListenerRegistered() {
+ val mockChipbarCoordinator = mock<ChipbarCoordinator>()
+ underTest =
+ MediaTttSenderCoordinator(
+ mockChipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+ // Re-set the command queue callback since we've created a new [MediaTttSenderCoordinator]
+ // with a new callback.
+ setCommandQueueCallback()
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ routeInfo,
+ null,
+ )
+
+ verify(mockChipbarCoordinator).registerListener(any())
+ }
+
+ @Test
+ fun onInfoPermanentlyRemoved_viewListenerUnregistered() {
+ val mockChipbarCoordinator = mock<ChipbarCoordinator>()
+ underTest =
+ MediaTttSenderCoordinator(
+ mockChipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+ setCommandQueueCallback()
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ routeInfo,
+ null,
+ )
+
+ val listenerCaptor = argumentCaptor<TemporaryViewDisplayController.Listener>()
+ verify(mockChipbarCoordinator).registerListener(capture(listenerCaptor))
+
+ // WHEN the listener is notified that the view has been removed
+ listenerCaptor.value.onInfoPermanentlyRemoved(DEFAULT_ID)
+
+ // THEN the media coordinator unregisters the listener
+ verify(mockChipbarCoordinator).unregisterListener(listenerCaptor.value)
+ }
+
+ @Test
+ fun onInfoPermanentlyRemoved_wrongId_viewListenerNotUnregistered() {
+ val mockChipbarCoordinator = mock<ChipbarCoordinator>()
+ underTest =
+ MediaTttSenderCoordinator(
+ mockChipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+ setCommandQueueCallback()
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ routeInfo,
+ null,
+ )
+
+ val listenerCaptor = argumentCaptor<TemporaryViewDisplayController.Listener>()
+ verify(mockChipbarCoordinator).registerListener(capture(listenerCaptor))
+
+ // WHEN the listener is notified that a different view has been removed
+ listenerCaptor.value.onInfoPermanentlyRemoved("differentViewId")
+
+ // THEN the media coordinator doesn't unregister the listener
+ verify(mockChipbarCoordinator, never()).unregisterListener(listenerCaptor.value)
+ }
+
+ @Test
+ fun farFromReceiverState_viewListenerUnregistered() {
+ val mockChipbarCoordinator = mock<ChipbarCoordinator>()
+ underTest =
+ MediaTttSenderCoordinator(
+ mockChipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+ setCommandQueueCallback()
+
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ routeInfo,
+ null,
+ )
+
+ val listenerCaptor = argumentCaptor<TemporaryViewDisplayController.Listener>()
+ verify(mockChipbarCoordinator).registerListener(capture(listenerCaptor))
+
+ // WHEN we go to the FAR_FROM_RECEIVER state
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER,
+ routeInfo,
+ null
+ )
+
+ // THEN the media coordinator unregisters the listener
+ verify(mockChipbarCoordinator).unregisterListener(listenerCaptor.value)
+ }
+
+ @Test
+ fun statesWithDifferentIds_onInfoPermanentlyRemovedForOneId_viewListenerNotUnregistered() {
+ val mockChipbarCoordinator = mock<ChipbarCoordinator>()
+ underTest =
+ MediaTttSenderCoordinator(
+ mockChipbarCoordinator,
+ commandQueue,
+ context,
+ logger,
+ mediaTttFlags,
+ uiEventLogger,
+ )
+ underTest.start()
+ setCommandQueueCallback()
+
+ // WHEN there are two different media transfers with different IDs
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ MediaRoute2Info.Builder("route1", OTHER_DEVICE_NAME)
+ .addFeature("feature")
+ .setClientPackageName(PACKAGE_NAME)
+ .build(),
+ null,
+ )
+ commandQueueCallback.updateMediaTapToTransferSenderDisplay(
+ StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST,
+ MediaRoute2Info.Builder("route2", OTHER_DEVICE_NAME)
+ .addFeature("feature")
+ .setClientPackageName(PACKAGE_NAME)
+ .build(),
+ null,
+ )
+
+ val listenerCaptor = argumentCaptor<TemporaryViewDisplayController.Listener>()
+ verify(mockChipbarCoordinator, atLeast(1)).registerListener(capture(listenerCaptor))
+
+ // THEN one of them is removed
+ listenerCaptor.value.onInfoPermanentlyRemoved("route1")
+
+ // THEN the media coordinator doesn't unregister the listener (since route2 is still active)
+ verify(mockChipbarCoordinator, never()).unregisterListener(listenerCaptor.value)
+ }
+
private fun getChipbarView(): ViewGroup {
val viewCaptor = ArgumentCaptor.forClass(View::class.java)
verify(windowManager).addView(viewCaptor.capture(), any())
@@ -960,8 +1132,16 @@
null
)
}
+
+ private fun setCommandQueueCallback() {
+ val callbackCaptor = argumentCaptor<CommandQueue.Callbacks>()
+ verify(commandQueue).addCallback(capture(callbackCaptor))
+ commandQueueCallback = callbackCaptor.value
+ reset(commandQueue)
+ }
}
+private const val DEFAULT_ID = "defaultId"
private const val APP_NAME = "Fake app name"
private const val OTHER_DEVICE_NAME = "My Tablet"
private const val BLANK_DEVICE_NAME = " "
@@ -969,13 +1149,13 @@
private const val TIMEOUT = 10000
private val routeInfo =
- MediaRoute2Info.Builder("id", OTHER_DEVICE_NAME)
+ MediaRoute2Info.Builder(DEFAULT_ID, OTHER_DEVICE_NAME)
.addFeature("feature")
.setClientPackageName(PACKAGE_NAME)
.build()
private val routeInfoWithBlankDeviceName =
- MediaRoute2Info.Builder("id", BLANK_DEVICE_NAME)
+ MediaRoute2Info.Builder(DEFAULT_ID, BLANK_DEVICE_NAME)
.addFeature("feature")
.setClientPackageName(PACKAGE_NAME)
.build()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
index 1bc4719..1a35502 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
@@ -31,10 +31,7 @@
import org.junit.runner.RunWith;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -69,7 +66,7 @@
// Expressive applies hue rotations to the theme color. The input theme color has hue
// 117, ensuring the hue changed significantly is a strong signal styles are being applied.
ColorScheme colorScheme = new ColorScheme(wallpaperColors, false, Style.EXPRESSIVE);
- Assert.assertEquals(357.77, Cam.fromInt(colorScheme.getAccent1().get(6)).getHue(), 0.1);
+ Assert.assertEquals(357.77, Cam.fromInt(colorScheme.getAccent1().getS500()).getHue(), 0.1);
}
@@ -111,7 +108,8 @@
public void testTertiaryHueWrapsProperly() {
int colorInt = 0xffB3588A; // H350 C50 T50
ColorScheme colorScheme = new ColorScheme(colorInt, false /* darkTheme */);
- int tertiaryMid = colorScheme.getAccent3().get(colorScheme.getAccent3().size() / 2);
+ int tertiaryMid = colorScheme.getAccent3().getAllShades().get(
+ colorScheme.getShadeCount() / 2);
Cam cam = Cam.fromInt(tertiaryMid);
Assert.assertEquals(cam.getHue(), 50.0, 10.0);
}
@@ -121,7 +119,8 @@
int colorInt = 0xffB3588A; // H350 C50 T50
ColorScheme colorScheme = new ColorScheme(colorInt, false /* darkTheme */,
Style.SPRITZ /* style */);
- int primaryMid = colorScheme.getAccent1().get(colorScheme.getAccent1().size() / 2);
+ int primaryMid = colorScheme.getAccent1().getAllShades().get(
+ colorScheme.getShadeCount() / 2);
Cam cam = Cam.fromInt(primaryMid);
Assert.assertEquals(cam.getChroma(), 12.0, 1.0);
}
@@ -131,7 +130,8 @@
int colorInt = 0xffB3588A; // H350 C50 T50
ColorScheme colorScheme = new ColorScheme(colorInt, false /* darkTheme */,
Style.VIBRANT /* style */);
- int neutralMid = colorScheme.getNeutral1().get(colorScheme.getNeutral1().size() / 2);
+ int neutralMid = colorScheme.getNeutral1().getAllShades().get(
+ colorScheme.getShadeCount() / 2);
Cam cam = Cam.fromInt(neutralMid);
Assert.assertTrue("chroma was " + cam.getChroma(), Math.floor(cam.getChroma()) <= 12.0);
}
@@ -141,7 +141,8 @@
int colorInt = 0xffB3588A; // H350 C50 T50
ColorScheme colorScheme = new ColorScheme(colorInt, false /* darkTheme */,
Style.EXPRESSIVE /* style */);
- int neutralMid = colorScheme.getNeutral1().get(colorScheme.getNeutral1().size() / 2);
+ int neutralMid = colorScheme.getNeutral1().getAllShades().get(
+ colorScheme.getShadeCount() / 2);
Cam cam = Cam.fromInt(neutralMid);
Assert.assertTrue(cam.getChroma() <= 8.0);
}
@@ -151,10 +152,11 @@
int colorInt = 0xffB3588A; // H350 C50 T50
ColorScheme colorScheme = new ColorScheme(colorInt, false /* darkTheme */,
Style.MONOCHROMATIC /* style */);
- int neutralMid = colorScheme.getNeutral1().get(colorScheme.getNeutral1().size() / 2);
+ int neutralMid = colorScheme.getNeutral1().getAllShades().get(
+ colorScheme.getShadeCount() / 2);
Assert.assertTrue(
Color.red(neutralMid) == Color.green(neutralMid)
- && Color.green(neutralMid) == Color.blue(neutralMid)
+ && Color.green(neutralMid) == Color.blue(neutralMid)
);
}
@@ -190,15 +192,14 @@
xml.append(" <").append(styleName).append(">");
List<String> colors = new ArrayList<>();
- for (Stream<Integer> stream: Arrays.asList(colorScheme.getAccent1().stream(),
- colorScheme.getAccent2().stream(),
- colorScheme.getAccent3().stream(),
- colorScheme.getNeutral1().stream(),
- colorScheme.getNeutral2().stream())) {
+
+ colorScheme.getAllHues().forEach(schemeHue -> {
colors.add("ffffff");
- colors.addAll(stream.map(Integer::toHexString).map(s -> s.substring(2)).collect(
- Collectors.toList()));
- }
+ schemeHue.getAllShades().forEach(tone -> {
+ colors.add(Integer.toHexString(tone).substring(2));
+ });
+ });
+
xml.append(String.join(",", colors));
xml.append("</").append(styleName).append(">\n");
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 8b0342e..8058b85 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -55,8 +55,8 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -109,7 +109,8 @@
TaskStackChangeListeners.getTestInstance(),
Optional.of(mock(Pip.class)),
Optional.of(mock(BackAnimation.class)),
- mock(FeatureFlags.class)));
+ mock(FeatureFlags.class),
+ mock(SecureSettings.class)));
initializeNavigationBars();
mMockitoSession = mockitoSession().mockStatic(Utilities.class).startMocking();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
new file mode 100644
index 0000000..a1d42a0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfigTest.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.notetask.quickaffordance
+
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.shared.model.ContentDescription
+import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.LockScreenState
+import com.android.systemui.notetask.NoteTaskController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+/**
+ * Tests for [NoteTaskQuickAffordanceConfig].
+ *
+ * Build/Install/Run:
+ * - atest SystemUITests:NoteTaskQuickAffordanceConfigTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskQuickAffordanceConfigTest : SysuiTestCase() {
+
+ @Mock lateinit var noteTaskController: NoteTaskController
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(noteTaskController.showNoteTask()).then {}
+ }
+
+ private fun createUnderTest(isEnabled: Boolean) =
+ NoteTaskQuickAffordanceConfig(
+ context = context,
+ noteTaskController = noteTaskController,
+ isEnabled = isEnabled,
+ )
+
+ @Test
+ fun lockScreenState_isNotEnabled_shouldEmitHidden() = runTest {
+ val underTest = createUnderTest(isEnabled = false)
+
+ val actual = collectLastValue(underTest.lockScreenState)
+
+ assertThat(actual()).isEqualTo(LockScreenState.Hidden)
+ }
+
+ @Test
+ fun lockScreenState_isEnabled_shouldEmitVisible() = runTest {
+ val stringResult = "Notetaking"
+ val underTest = createUnderTest(isEnabled = true)
+
+ val actual = collectLastValue(underTest.lockScreenState)
+
+ val expected =
+ LockScreenState.Visible(
+ icon =
+ Icon.Resource(
+ res = R.drawable.ic_note_task_shortcut_keyguard,
+ contentDescription = ContentDescription.Loaded(stringResult),
+ )
+ )
+ assertThat(actual()).isEqualTo(expected)
+ }
+
+ @Test
+ fun onTriggered_shouldLaunchNoteTask() {
+ val underTest = createUnderTest(isEnabled = false)
+
+ underTest.onTriggered(expandable = null)
+
+ verify(noteTaskController).showNoteTask()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 3528e14..3da7a22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -30,6 +30,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
@@ -54,6 +55,7 @@
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.broadcast.BroadcastSender;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.settings.FakeSettings;
@@ -86,6 +88,8 @@
@Mock
private UiEventLogger mUiEventLogger;
@Mock
+ private UserTracker mUserTracker;
+ @Mock
private View mView;
private BroadcastReceiver mReceiver;
@@ -107,9 +111,12 @@
mContext.addMockSystemService(NotificationManager.class, mMockNotificationManager);
ActivityStarter starter = mDependency.injectMockDependency(ActivityStarter.class);
BroadcastSender broadcastSender = mDependency.injectMockDependency(BroadcastSender.class);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
+ when(mUserTracker.getUserHandle()).thenReturn(
+ UserHandle.of(ActivityManager.getCurrentUser()));
mPowerNotificationWarnings = new PowerNotificationWarnings(wrapper, starter,
broadcastSender, () -> mBatteryController, mDialogLaunchAnimator, mUiEventLogger,
- mGlobalSettings);
+ mGlobalSettings, mUserTracker);
BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1,
BatteryManager.BATTERY_HEALTH_GOOD, 5, 15);
mPowerNotificationWarnings.updateSnapshot(snapshot);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
index 46a502a..ed3f1a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
@@ -22,15 +22,12 @@
import android.graphics.Insets
import android.graphics.Rect
import android.hardware.HardwareBuffer
-import android.os.Bundle
import android.os.UserHandle
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD
import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER
import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
-import com.android.internal.util.ScreenshotHelper.HardwareBitmapBundler
-import com.android.internal.util.ScreenshotHelper.HardwareBitmapBundler.bundleToHardwareBitmap
-import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
+import com.android.internal.util.ScreenshotRequest
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
@@ -49,7 +46,6 @@
private val bounds = Rect(25, 25, 75, 75)
private val scope = CoroutineScope(Dispatchers.Unconfined)
- private val dispatcher = Dispatchers.Unconfined
private val policy = FakeScreenshotPolicy()
private val flags = FakeFeatureFlags()
@@ -58,7 +54,8 @@
fun testProcessAsync() {
flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
val processor = RequestProcessor(imageCapture, policy, flags, scope)
var result: ScreenshotRequest? = null
@@ -80,7 +77,8 @@
fun testFullScreenshot_workProfilePolicyDisabled() = runBlocking {
flags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
val processor = RequestProcessor(imageCapture, policy, flags, scope)
val processedRequest = processor.process(request)
@@ -97,9 +95,11 @@
policy.setManagedProfile(USER_ID, false)
policy.setDisplayContentInfo(
policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID)
+ )
- val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_OTHER)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_OTHER).build()
val processor = RequestProcessor(imageCapture, policy, flags, scope)
val processedRequest = processor.process(request)
@@ -120,17 +120,20 @@
// Indicate that the primary content belongs to a manged profile
policy.setManagedProfile(USER_ID, true)
- policy.setDisplayContentInfo(policy.getDefaultDisplayId(),
- DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID))
+ policy.setDisplayContentInfo(
+ policy.getDefaultDisplayId(),
+ DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID)
+ )
- val request = ScreenshotRequest(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD).build()
val processor = RequestProcessor(imageCapture, policy, flags, scope)
val processedRequest = processor.process(request)
// Expect a task snapshot is taken, overriding the full screen mode
assertThat(processedRequest.type).isEqualTo(TAKE_SCREENSHOT_PROVIDED_IMAGE)
- assertThat(bitmap.equalsHardwareBitmapBundle(processedRequest.bitmapBundle)).isTrue()
+ assertThat(bitmap.equalsHardwareBitmap(processedRequest.bitmap)).isTrue()
assertThat(processedRequest.boundsInScreen).isEqualTo(bounds)
assertThat(processedRequest.insets).isEqualTo(Insets.NONE)
assertThat(processedRequest.taskId).isEqualTo(TASK_ID)
@@ -147,10 +150,16 @@
val processor = RequestProcessor(imageCapture, policy, flags, scope)
val bitmap = makeHardwareBitmap(100, 100)
- val bitmapBundle = HardwareBitmapBundler.hardwareBitmapToBundle(bitmap)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER,
- bitmapBundle, bounds, Insets.NONE, TASK_ID, USER_ID, component)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(component)
+ .setTaskId(TASK_ID)
+ .setUserId(USER_ID)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(bounds)
+ .setInsets(Insets.NONE)
+ .build()
val processedRequest = processor.process(request)
@@ -168,10 +177,16 @@
policy.setManagedProfile(USER_ID, false)
val bitmap = makeHardwareBitmap(100, 100)
- val bitmapBundle = HardwareBitmapBundler.hardwareBitmapToBundle(bitmap)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER,
- bitmapBundle, bounds, Insets.NONE, TASK_ID, USER_ID, component)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(component)
+ .setTaskId(TASK_ID)
+ .setUserId(USER_ID)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(bounds)
+ .setInsets(Insets.NONE)
+ .build()
val processedRequest = processor.process(request)
@@ -190,10 +205,16 @@
policy.setManagedProfile(USER_ID, true)
val bitmap = makeHardwareBitmap(100, 100)
- val bitmapBundle = HardwareBitmapBundler.hardwareBitmapToBundle(bitmap)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER,
- bitmapBundle, bounds, Insets.NONE, TASK_ID, USER_ID, component)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(component)
+ .setTaskId(TASK_ID)
+ .setUserId(USER_ID)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(bounds)
+ .setInsets(Insets.NONE)
+ .build()
val processedRequest = processor.process(request)
@@ -202,14 +223,18 @@
}
private fun makeHardwareBitmap(width: Int, height: Int): Bitmap {
- val buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888, 1,
- HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)
+ val buffer =
+ HardwareBuffer.create(
+ width,
+ height,
+ HardwareBuffer.RGBA_8888,
+ 1,
+ HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
+ )
return Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB))!!
}
- private fun Bitmap.equalsHardwareBitmapBundle(bundle: Bundle): Boolean {
- val provided = bundleToHardwareBitmap(bundle)
- return provided.hardwareBuffer == this.hardwareBuffer &&
- provided.colorSpace == this.colorSpace
+ private fun Bitmap.equalsHardwareBitmap(bitmap: Bitmap): Boolean {
+ return bitmap.hardwareBuffer == this.hardwareBuffer && bitmap.colorSpace == this.colorSpace
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
index 99c79b0..f935019 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
@@ -35,8 +35,7 @@
import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
-import com.android.internal.util.ScreenshotHelper
-import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
+import com.android.internal.util.ScreenshotRequest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
@@ -80,24 +79,39 @@
private val flags = FakeFeatureFlags()
private val topComponent = ComponentName(mContext, TakeScreenshotServiceTest::class.java)
- private val service = TakeScreenshotService(
- controller, userManager, devicePolicyManager, eventLogger,
- notificationsController, mContext, Runnable::run, flags, requestProcessor)
+ private val service =
+ TakeScreenshotService(
+ controller,
+ userManager,
+ devicePolicyManager,
+ eventLogger,
+ notificationsController,
+ mContext,
+ Runnable::run,
+ flags,
+ requestProcessor
+ )
@Before
fun setUp() {
whenever(devicePolicyManager.resources).thenReturn(devicePolicyResourcesManager)
- whenever(devicePolicyManager.getScreenCaptureDisabled(
- /* admin component (null: any admin) */ isNull(), eq(UserHandle.USER_ALL)))
+ whenever(
+ devicePolicyManager.getScreenCaptureDisabled(
+ /* admin component (null: any admin) */ isNull(),
+ eq(UserHandle.USER_ALL)
+ )
+ )
.thenReturn(false)
whenever(userManager.isUserUnlocked).thenReturn(true)
// Stub request processor as a synchronous no-op for tests with the flag enabled
doAnswer {
- val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
- val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
- consumer.accept(request)
- }.`when`(requestProcessor).processAsync(/* request= */ any(), /* callback= */ any())
+ val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
+ val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
+ consumer.accept(request)
+ }
+ .`when`(requestProcessor)
+ .processAsync(/* request= */ any(), /* callback= */ any())
// Flipped in selected test cases
flags.set(SCREENSHOT_WORK_PROFILE_POLICY, false)
@@ -108,7 +122,8 @@
/* className = */ null,
/* token = */ null,
application,
- /* activityManager = */ null)
+ /* activityManager = */ null
+ )
}
@Test
@@ -125,63 +140,89 @@
@Test
fun takeScreenshotFullscreen() {
- val request = ScreenshotRequest(
- TAKE_SCREENSHOT_FULLSCREEN,
- SCREENSHOT_KEY_CHORD,
- topComponent)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ .setTopComponent(topComponent)
+ .build()
- service.handleRequest(request, { /* onSaved */ }, callback)
+ service.handleRequest(request, { /* onSaved */}, callback)
- verify(controller, times(1)).takeScreenshotFullscreen(
- eq(topComponent),
- /* onSavedListener = */ any(),
- /* requestCallback = */ any())
+ verify(controller, times(1))
+ .takeScreenshotFullscreen(
+ eq(topComponent),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any()
+ )
assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
val logEvent = eventLogger.get(0)
- assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
- logEvent.eventId, SCREENSHOT_REQUESTED_KEY_CHORD.id)
- assertEquals("Expected supplied package name",
- topComponent.packageName, eventLogger.get(0).packageName)
+ assertEquals(
+ "Expected SCREENSHOT_REQUESTED UiEvent",
+ logEvent.eventId,
+ SCREENSHOT_REQUESTED_KEY_CHORD.id
+ )
+ assertEquals(
+ "Expected supplied package name",
+ topComponent.packageName,
+ eventLogger.get(0).packageName
+ )
}
@Test
fun takeScreenshotProvidedImage() {
val bounds = Rect(50, 50, 150, 150)
val bitmap = makeHardwareBitmap(100, 100)
- val bitmapBundle = ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(bitmap)
- val request = ScreenshotRequest(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW,
- bitmapBundle, bounds, Insets.NONE, TASK_ID, USER_ID, topComponent)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW)
+ .setTopComponent(topComponent)
+ .setTaskId(TASK_ID)
+ .setUserId(USER_ID)
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(bounds)
+ .setInsets(Insets.NONE)
+ .build()
- service.handleRequest(request, { /* onSaved */ }, callback)
+ service.handleRequest(request, { /* onSaved */}, callback)
- verify(controller, times(1)).handleImageAsScreenshot(
- argThat { b -> b.equalsHardwareBitmap(bitmap) },
- eq(bounds),
- eq(Insets.NONE), eq(TASK_ID), eq(USER_ID), eq(topComponent),
- /* onSavedListener = */ any(), /* requestCallback = */ any())
+ verify(controller, times(1))
+ .handleImageAsScreenshot(
+ argThat { b -> b.equalsHardwareBitmap(bitmap) },
+ eq(bounds),
+ eq(Insets.NONE),
+ eq(TASK_ID),
+ eq(USER_ID),
+ eq(topComponent),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any()
+ )
assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
val logEvent = eventLogger.get(0)
- assertEquals("Expected SCREENSHOT_REQUESTED_* UiEvent",
- logEvent.eventId, SCREENSHOT_REQUESTED_OVERVIEW.id)
- assertEquals("Expected supplied package name",
- topComponent.packageName, eventLogger.get(0).packageName)
+ assertEquals(
+ "Expected SCREENSHOT_REQUESTED_* UiEvent",
+ logEvent.eventId,
+ SCREENSHOT_REQUESTED_OVERVIEW.id
+ )
+ assertEquals(
+ "Expected supplied package name",
+ topComponent.packageName,
+ eventLogger.get(0).packageName
+ )
}
@Test
fun takeScreenshotFullscreen_userLocked() {
whenever(userManager.isUserUnlocked).thenReturn(false)
- val request = ScreenshotRequest(
- TAKE_SCREENSHOT_FULLSCREEN,
- SCREENSHOT_KEY_CHORD,
- topComponent)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ .setTopComponent(topComponent)
+ .build()
- service.handleRequest(request, { /* onSaved */ }, callback)
+ service.handleRequest(request, { /* onSaved */}, callback)
verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
verify(callback, times(1)).reportError()
@@ -190,21 +231,24 @@
@Test
fun takeScreenshotFullscreen_screenCaptureDisabled_allUsers() {
- whenever(devicePolicyManager.getScreenCaptureDisabled(
- isNull(), eq(UserHandle.USER_ALL))
- ).thenReturn(true)
+ whenever(devicePolicyManager.getScreenCaptureDisabled(isNull(), eq(UserHandle.USER_ALL)))
+ .thenReturn(true)
- whenever(devicePolicyResourcesManager.getString(
- eq(SCREENSHOT_BLOCKED_BY_ADMIN),
- /* Supplier<String> */ any(),
- )).thenReturn("SCREENSHOT_BLOCKED_BY_ADMIN")
+ whenever(
+ devicePolicyResourcesManager.getString(
+ eq(SCREENSHOT_BLOCKED_BY_ADMIN),
+ /* Supplier<String> */
+ any(),
+ )
+ )
+ .thenReturn("SCREENSHOT_BLOCKED_BY_ADMIN")
- val request = ScreenshotRequest(
- TAKE_SCREENSHOT_FULLSCREEN,
- SCREENSHOT_KEY_CHORD,
- topComponent)
+ val request =
+ ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_CHORD)
+ .setTopComponent(topComponent)
+ .build()
- service.handleRequest(request, { /* onSaved */ }, callback)
+ service.handleRequest(request, { /* onSaved */}, callback)
// error shown: Toast.makeText(...).show(), untestable
verify(callback, times(1)).reportError()
@@ -214,14 +258,20 @@
private fun Bitmap.equalsHardwareBitmap(other: Bitmap): Boolean {
return config == HARDWARE &&
- other.config == HARDWARE &&
- hardwareBuffer == other.hardwareBuffer &&
- colorSpace == other.colorSpace
+ other.config == HARDWARE &&
+ hardwareBuffer == other.hardwareBuffer &&
+ colorSpace == other.colorSpace
}
/** A hardware Bitmap is mandated by use of ScreenshotHelper.HardwareBitmapBundler */
private fun makeHardwareBitmap(width: Int, height: Int): Bitmap {
- val buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888, 1,
- HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)
+ val buffer =
+ HardwareBuffer.create(
+ width,
+ height,
+ HardwareBuffer.RGBA_8888,
+ 1,
+ HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
+ )
return Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB))!!
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
index 3710281..57b6b2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.settings
+import android.app.IActivityManager
import android.content.Context
import android.content.Intent
import android.content.pm.UserInfo
@@ -51,6 +52,7 @@
@Mock private lateinit var context: Context
@Mock private lateinit var userManager: UserManager
+ @Mock private lateinit var iActivityManager: IActivityManager
@Mock(stubOnly = true) private lateinit var dumpManager: DumpManager
@Mock(stubOnly = true) private lateinit var handler: Handler
@@ -67,7 +69,7 @@
`when`(context.user).thenReturn(UserHandle.SYSTEM)
`when`(context.createContextAsUser(ArgumentMatchers.any(), anyInt())).thenReturn(context)
- tracker = UserTrackerImpl(context, userManager, dumpManager, handler)
+ tracker = UserTrackerImpl(context, userManager, iActivityManager, dumpManager, handler)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index e65bbb1..71ba215 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -16,11 +16,14 @@
package com.android.systemui.settings
+import android.app.IActivityManager
+import android.app.IUserSwitchObserver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.UserInfo
import android.os.Handler
+import android.os.IRemoteCallback
import android.os.UserHandle
import android.os.UserManager
import android.testing.AndroidTestingRunner
@@ -29,19 +32,20 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.mockito.capture
import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.ArgumentMatchers.isNull
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.concurrent.Executor
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -51,6 +55,10 @@
private lateinit var context: Context
@Mock
private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var iActivityManager: IActivityManager
+ @Mock
+ private lateinit var userSwitchingReply: IRemoteCallback
@Mock(stubOnly = true)
private lateinit var dumpManager: DumpManager
@Mock(stubOnly = true)
@@ -76,7 +84,7 @@
listOf(info)
}
- tracker = UserTrackerImpl(context, userManager, dumpManager, handler)
+ tracker = UserTrackerImpl(context, userManager, iActivityManager, dumpManager, handler)
}
@Test
@@ -125,8 +133,7 @@
verify(context).registerReceiverForAllUsers(
eq(tracker), capture(captor), isNull(), eq(handler))
with(captor.value) {
- assertThat(countActions()).isEqualTo(7)
- assertThat(hasAction(Intent.ACTION_USER_SWITCHED)).isTrue()
+ assertThat(countActions()).isEqualTo(6)
assertThat(hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue()
assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)).isTrue()
assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)).isTrue()
@@ -158,8 +165,10 @@
tracker.initialize(0)
val newID = 5
- val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, newID)
- tracker.onReceive(context, intent)
+ val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
+ verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onUserSwitching(newID, userSwitchingReply)
+ verify(userSwitchingReply).sendResult(any())
verify(userManager).getProfiles(newID)
@@ -272,6 +281,24 @@
}
@Test
+ fun testCallbackCalledOnUserChanging() {
+ tracker.initialize(0)
+ val callback = TestCallback()
+ tracker.addCallback(callback, executor)
+
+ val newID = 5
+
+ val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
+ verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onUserSwitching(newID, userSwitchingReply)
+ verify(userSwitchingReply).sendResult(any())
+
+ assertThat(callback.calledOnUserChanging).isEqualTo(1)
+ assertThat(callback.lastUser).isEqualTo(newID)
+ assertThat(callback.lastUserContext?.userId).isEqualTo(newID)
+ }
+
+ @Test
fun testCallbackCalledOnUserChanged() {
tracker.initialize(0)
val callback = TestCallback()
@@ -279,8 +306,9 @@
val newID = 5
- val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, newID)
- tracker.onReceive(context, intent)
+ val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
+ verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onUserSwitchComplete(newID)
assertThat(callback.calledOnUserChanged).isEqualTo(1)
assertThat(callback.lastUser).isEqualTo(newID)
@@ -330,25 +358,36 @@
tracker.addCallback(callback, executor)
tracker.removeCallback(callback)
- val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, 5)
- tracker.onReceive(context, intent)
+ val captor = ArgumentCaptor.forClass(IUserSwitchObserver::class.java)
+ verify(iActivityManager).registerUserSwitchObserver(capture(captor), anyString())
+ captor.value.onUserSwitching(newID, userSwitchingReply)
+ verify(userSwitchingReply).sendResult(any())
+ captor.value.onUserSwitchComplete(newID)
val intentProfiles = Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
.putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
tracker.onReceive(context, intentProfiles)
+ assertThat(callback.calledOnUserChanging).isEqualTo(0)
assertThat(callback.calledOnUserChanged).isEqualTo(0)
assertThat(callback.calledOnProfilesChanged).isEqualTo(0)
}
private class TestCallback : UserTracker.Callback {
+ var calledOnUserChanging = 0
var calledOnUserChanged = 0
var calledOnProfilesChanged = 0
var lastUser: Int? = null
var lastUserContext: Context? = null
var lastUserProfiles = emptyList<UserInfo>()
+ override fun onUserChanging(newUser: Int, userContext: Context) {
+ calledOnUserChanging++
+ lastUser = newUser
+ lastUserContext = userContext
+ }
+
override fun onUserChanged(newUser: Int, userContext: Context) {
calledOnUserChanged++
lastUser = newUser
@@ -360,4 +399,4 @@
lastUserProfiles = profiles
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
index f802a5e..ed9baf5b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
@@ -109,11 +109,12 @@
@Test
fun testEdgeElementsAlignedWithEdge_largeScreen() {
with(largeScreenConstraint) {
- assertThat(getConstraint(R.id.clock).layout.startToStart).isEqualTo(PARENT_ID)
- assertThat(getConstraint(R.id.clock).layout.horizontalBias).isEqualTo(0f)
+ assertThat(getConstraint(R.id.clock).layout.startToEnd).isEqualTo(R.id.begin_guide)
+ assertThat(getConstraint(R.id.clock).layout.horizontalBias).isEqualTo(0.5f)
- assertThat(getConstraint(R.id.privacy_container).layout.endToEnd).isEqualTo(PARENT_ID)
- assertThat(getConstraint(R.id.privacy_container).layout.horizontalBias).isEqualTo(1f)
+ assertThat(getConstraint(R.id.privacy_container).layout.endToStart)
+ .isEqualTo(R.id.end_guide)
+ assertThat(getConstraint(R.id.privacy_container).layout.horizontalBias).isEqualTo(0.5f)
}
}
@@ -219,7 +220,12 @@
.isEqualTo(cutoutEnd - padding)
}
- assertThat(changes.largeScreenConstraintsChanges).isNull()
+ with(largeScreenConstraint) {
+ assertThat(getConstraint(R.id.begin_guide).layout.guideBegin)
+ .isEqualTo(cutoutStart - padding)
+ assertThat(getConstraint(R.id.end_guide).layout.guideEnd)
+ .isEqualTo(cutoutEnd - padding)
+ }
}
@Test
@@ -246,7 +252,10 @@
assertThat(getConstraint(R.id.end_guide).layout.guideEnd).isEqualTo(0)
}
- assertThat(changes.largeScreenConstraintsChanges).isNull()
+ with(largeScreenConstraint) {
+ assertThat(getConstraint(R.id.begin_guide).layout.guideBegin).isEqualTo(0)
+ assertThat(getConstraint(R.id.end_guide).layout.guideEnd).isEqualTo(0)
+ }
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
index 3e769e9..76aa08a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.tuner.TunerService
import com.android.systemui.tuner.TunerService.Tunable
@@ -69,6 +70,8 @@
private lateinit var statusBarStateController: StatusBarStateController
@Mock
private lateinit var shadeLogger: ShadeLogger
+ @Mock
+ private lateinit var userTracker: UserTracker
private lateinit var tunableCaptor: ArgumentCaptor<Tunable>
private lateinit var underTest: PulsingGestureListener
@@ -85,6 +88,7 @@
ambientDisplayConfiguration,
statusBarStateController,
shadeLogger,
+ userTracker,
tunerService,
dumpManager
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt
new file mode 100644
index 0000000..5fb1e79
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/BcSmartspaceConfigProviderTest.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.smartspace
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.smartspace.config.BcSmartspaceConfigProvider
+import com.android.systemui.util.mockito.whenever
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class BcSmartspaceConfigProviderTest : SysuiTestCase() {
+ @Mock private lateinit var featureFlags: FeatureFlags
+
+ private lateinit var configProvider: BcSmartspaceConfigProvider
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ configProvider = BcSmartspaceConfigProvider(featureFlags)
+ }
+
+ @Test
+ fun isDefaultDateWeatherDisabled_flagIsTrue_returnsTrue() {
+ whenever(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
+
+ assertTrue(configProvider.isDefaultDateWeatherDisabled)
+ }
+
+ @Test
+ fun isDefaultDateWeatherDisabled_flagIsFalse_returnsFalse() {
+ whenever(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
+
+ assertFalse(configProvider.isDefaultDateWeatherDisabled)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
index 001e1f4..c5432c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
@@ -27,6 +27,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dreams.smartspace.DreamSmartspaceController
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
@@ -94,6 +95,8 @@
private class TestView(context: Context?) : View(context), SmartspaceView {
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {}
+ override fun registerConfigProvider(plugin: BcSmartspaceConfigPlugin?) {}
+
override fun setPrimaryTextColor(color: Int) {}
override fun setIsDreaming(isDreaming: Boolean) {}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index ddcf59e..4bcb54d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -36,6 +36,7 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.BcSmartspaceConfigPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
@@ -115,6 +116,9 @@
private lateinit var plugin: BcSmartspaceDataPlugin
@Mock
+ private lateinit var configPlugin: BcSmartspaceConfigPlugin
+
+ @Mock
private lateinit var controllerListener: SmartspaceTargetListener
@Captor
@@ -209,7 +213,8 @@
executor,
bgExecutor,
handler,
- Optional.of(plugin)
+ Optional.of(plugin),
+ Optional.of(configPlugin),
)
verify(deviceProvisionedController).addCallback(capture(deviceProvisionedCaptor))
@@ -520,6 +525,7 @@
verify(smartspaceManager, never()).createSmartspaceSession(any())
verify(smartspaceView2).setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
verify(smartspaceView2).registerDataProvider(plugin)
+ verify(smartspaceView2).registerConfigProvider(configPlugin)
}
@Test
@@ -557,6 +563,7 @@
verify(smartspaceView).setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
verify(smartspaceView).registerDataProvider(plugin)
+ verify(smartspaceView).registerConfigProvider(configPlugin)
verify(smartspaceSession)
.addOnTargetsAvailableListener(any(), capture(sessionListenerCaptor))
sessionListener = sessionListenerCaptor.value
@@ -638,6 +645,9 @@
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
}
+ override fun registerConfigProvider(plugin: BcSmartspaceConfigPlugin?) {
+ }
+
override fun setPrimaryTextColor(color: Int) {
}
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 58fe2a0..831d07f 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
@@ -41,6 +41,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
@@ -59,6 +60,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -107,6 +109,8 @@
UiEventLoggerFake mUiEventLoggerFake;
@Mock
PendingIntent mPendingIntent;
+ @Mock
+ UserTracker mUserTracker;
private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider;
@@ -114,6 +118,7 @@
public void setup() {
MockitoAnnotations.initMocks(this);
when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(false);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
mUiEventLoggerFake = new UiEventLoggerFake();
@@ -131,7 +136,8 @@
mMockHandler,
mFlags,
mKeyguardNotificationVisibilityProvider,
- mUiEventLoggerFake);
+ mUiEventLoggerFake,
+ mUserTracker);
mNotifInterruptionStateProvider.mUseHeadsUp = true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 9d531a1..4559a23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -44,16 +44,23 @@
import android.app.Notification;
import android.app.NotificationChannel;
import android.graphics.Color;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.util.DisplayMetrics;
import android.view.View;
+import android.widget.ImageView;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
+import com.android.internal.widget.CachingIconView;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
@@ -61,6 +68,7 @@
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import org.junit.Assert;
@@ -72,6 +80,7 @@
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.Arrays;
import java.util.List;
@SmallTest
@@ -96,6 +105,9 @@
mDependency,
TestableLooper.get(this));
mNotificationTestHelper.setDefaultInflationFlags(FLAG_CONTENT_VIEW_ALL);
+ FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags();
+ fakeFeatureFlags.set(Flags.NOTIFICATION_ANIMATE_BIG_PICTURE, true);
+ mNotificationTestHelper.setFeatureFlags(fakeFeatureFlags);
// create a standard private notification row
Notification normalNotif = mNotificationTestHelper.createNotification();
normalNotif.publicVersion = null;
@@ -559,4 +571,123 @@
Assert.assertEquals(1f, mGroupRow.getBottomRoundness(), 0.001f);
Assert.assertEquals(1f, mGroupRow.getChildrenContainer().getBottomRoundness(), 0.001f);
}
+
+ @Test
+ public void testSetContentAnimationRunning_Run() throws Exception {
+ // Create views for the notification row.
+ NotificationContentView publicLayout = mock(NotificationContentView.class);
+ mNotifRow.setPublicLayout(publicLayout);
+ NotificationContentView privateLayout = mock(NotificationContentView.class);
+ mNotifRow.setPrivateLayout(privateLayout);
+
+ mNotifRow.setAnimationRunning(true);
+ verify(publicLayout, times(1)).setContentAnimationRunning(true);
+ verify(privateLayout, times(1)).setContentAnimationRunning(true);
+ }
+
+ @Test
+ public void testSetContentAnimationRunning_Stop() {
+ // Create views for the notification row.
+ NotificationContentView publicLayout = mock(NotificationContentView.class);
+ mNotifRow.setPublicLayout(publicLayout);
+ NotificationContentView privateLayout = mock(NotificationContentView.class);
+ mNotifRow.setPrivateLayout(privateLayout);
+
+ mNotifRow.setAnimationRunning(false);
+ verify(publicLayout, times(1)).setContentAnimationRunning(false);
+ verify(privateLayout, times(1)).setContentAnimationRunning(false);
+ }
+
+ @Test
+ public void testSetContentAnimationRunningInGroupChild_Run() {
+ // Creates parent views on mGroupRow.
+ NotificationContentView publicParentLayout = mock(NotificationContentView.class);
+ mGroupRow.setPublicLayout(publicParentLayout);
+ NotificationContentView privateParentLayout = mock(NotificationContentView.class);
+ mGroupRow.setPrivateLayout(privateParentLayout);
+
+ // Create child views on mNotifRow.
+ NotificationContentView publicChildLayout = mock(NotificationContentView.class);
+ mNotifRow.setPublicLayout(publicChildLayout);
+ NotificationContentView privateChildLayout = mock(NotificationContentView.class);
+ mNotifRow.setPrivateLayout(privateChildLayout);
+ when(mNotifRow.isGroupExpanded()).thenReturn(true);
+ setMockChildrenContainer(mGroupRow, mNotifRow);
+
+ mGroupRow.setAnimationRunning(true);
+ verify(publicParentLayout, times(1)).setContentAnimationRunning(true);
+ verify(privateParentLayout, times(1)).setContentAnimationRunning(true);
+ // The child layouts should be started too.
+ verify(publicChildLayout, times(1)).setContentAnimationRunning(true);
+ verify(privateChildLayout, times(1)).setContentAnimationRunning(true);
+ }
+
+
+ @Test
+ public void testSetIconAnimationRunningGroup_Run() {
+ // Create views for a group row.
+ NotificationContentView publicParentLayout = mock(NotificationContentView.class);
+ mGroupRow.setPublicLayout(publicParentLayout);
+ NotificationContentView privateParentLayout = mock(NotificationContentView.class);
+ mGroupRow.setPrivateLayout(privateParentLayout);
+ when(mGroupRow.isGroupExpanded()).thenReturn(true);
+
+ // Sets up mNotifRow as a child ExpandableNotificationRow.
+ NotificationContentView publicChildLayout = mock(NotificationContentView.class);
+ mNotifRow.setPublicLayout(publicChildLayout);
+ NotificationContentView privateChildLayout = mock(NotificationContentView.class);
+ mNotifRow.setPrivateLayout(privateChildLayout);
+ when(mNotifRow.isGroupExpanded()).thenReturn(true);
+
+ NotificationChildrenContainer mockContainer =
+ setMockChildrenContainer(mGroupRow, mNotifRow);
+
+ // Mock the children view wrappers, and give them each an icon.
+ NotificationViewWrapper mockViewWrapper = mock(NotificationViewWrapper.class);
+ when(mockContainer.getNotificationViewWrapper()).thenReturn(mockViewWrapper);
+ CachingIconView mockIcon = mock(CachingIconView.class);
+ when(mockViewWrapper.getIcon()).thenReturn(mockIcon);
+
+ NotificationViewWrapper mockLowPriorityViewWrapper = mock(NotificationViewWrapper.class);
+ when(mockContainer.getLowPriorityViewWrapper()).thenReturn(mockLowPriorityViewWrapper);
+ CachingIconView mockLowPriorityIcon = mock(CachingIconView.class);
+ when(mockLowPriorityViewWrapper.getIcon()).thenReturn(mockLowPriorityIcon);
+
+ // Give the icon image views drawables, so we can make sure they animate.
+ // We use both AnimationDrawables and AnimatedVectorDrawables to ensure both work.
+ AnimationDrawable drawable = mock(AnimationDrawable.class);
+ AnimatedVectorDrawable vectorDrawable = mock(AnimatedVectorDrawable.class);
+ setDrawableIconsInImageView(mockIcon, drawable, vectorDrawable);
+
+ AnimationDrawable lowPriDrawable = mock(AnimationDrawable.class);
+ AnimatedVectorDrawable lowPriVectorDrawable = mock(AnimatedVectorDrawable.class);
+ setDrawableIconsInImageView(mockLowPriorityIcon, lowPriDrawable, lowPriVectorDrawable);
+
+ mGroupRow.setAnimationRunning(true);
+ verify(drawable, times(1)).start();
+ verify(vectorDrawable, times(1)).start();
+ verify(lowPriDrawable, times(1)).start();
+ verify(lowPriVectorDrawable, times(1)).start();
+ }
+
+ private void setDrawableIconsInImageView(CachingIconView icon, Drawable iconDrawable,
+ Drawable rightIconDrawable) {
+ ImageView iconView = mock(ImageView.class);
+ when(icon.findViewById(com.android.internal.R.id.icon)).thenReturn(iconView);
+ when(iconView.getDrawable()).thenReturn(iconDrawable);
+
+ ImageView rightIconView = mock(ImageView.class);
+ when(icon.findViewById(com.android.internal.R.id.right_icon)).thenReturn(rightIconView);
+ when(rightIconView.getDrawable()).thenReturn(rightIconDrawable);
+ }
+
+ private NotificationChildrenContainer setMockChildrenContainer(
+ ExpandableNotificationRow parentRow, ExpandableNotificationRow childRow) {
+ List<ExpandableNotificationRow> rowList = Arrays.asList(childRow);
+ NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
+ when(mockContainer.getNotificationChildCount()).thenReturn(1);
+ when(mockContainer.getAttachedChildren()).thenReturn(rowList);
+ parentRow.setChildrenContainer(mockContainer);
+ return mockContainer;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java
index 1f92b0a..819a75b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FooterViewTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
@@ -98,5 +100,16 @@
mView.setSecondaryVisible(true /* visible */, true /* animate */);
}
+
+ @Test
+ public void testSetFooterLabelTextAndIcon() {
+ mView.setFooterLabelTextAndIcon(
+ R.string.unlock_to_see_notif_text,
+ R.drawable.ic_friction_lock_closed);
+ assertThat(mView.findViewById(R.id.manage_text).getVisibility()).isEqualTo(View.GONE);
+ assertThat(mView.findSecondaryView().getVisibility()).isEqualTo(View.GONE);
+ assertThat(mView.findViewById(R.id.unlock_prompt_footer).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
index 562b4df..7b2051d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
@@ -34,9 +34,12 @@
import com.android.systemui.statusbar.notification.FeedbackIcon
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,6 +47,7 @@
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations.initMocks
@@ -305,6 +309,86 @@
assertEquals(0, getMarginBottom(actionListMarginTarget))
}
+ @Test
+ fun onSetAnimationRunning() {
+ // Given: contractedWrapper, enpandedWrapper, and headsUpWrapper being set
+ val mockContracted = mock<NotificationViewWrapper>()
+ val mockExpanded = mock<NotificationViewWrapper>()
+ val mockHeadsUp = mock<NotificationViewWrapper>()
+
+ view.setContractedWrapper(mockContracted)
+ view.setExpandedWrapper(mockExpanded)
+ view.setHeadsUpWrapper(mockHeadsUp)
+
+ // When: we set content animation running.
+ assertTrue(view.setContentAnimationRunning(true))
+
+ // Then: contractedChild, expandedChild, and headsUpChild should have setAnimationsRunning
+ // called on them.
+ verify(mockContracted, times(1)).setAnimationsRunning(true)
+ verify(mockExpanded, times(1)).setAnimationsRunning(true)
+ verify(mockHeadsUp, times(1)).setAnimationsRunning(true)
+
+ // When: we set content animation running true _again_.
+ assertFalse(view.setContentAnimationRunning(true))
+
+ // Then: the children should not have setAnimationRunning called on them again.
+ // Verify counts number of calls so far on the object, so these still register as 1.
+ verify(mockContracted, times(1)).setAnimationsRunning(true)
+ verify(mockExpanded, times(1)).setAnimationsRunning(true)
+ verify(mockHeadsUp, times(1)).setAnimationsRunning(true)
+ }
+
+ @Test
+ fun onSetAnimationStopped() {
+ // Given: contractedWrapper, expandedWrapper, and headsUpWrapper being set
+ val mockContracted = mock<NotificationViewWrapper>()
+ val mockExpanded = mock<NotificationViewWrapper>()
+ val mockHeadsUp = mock<NotificationViewWrapper>()
+
+ view.setContractedWrapper(mockContracted)
+ view.setExpandedWrapper(mockExpanded)
+ view.setHeadsUpWrapper(mockHeadsUp)
+
+ // When: we set content animation running.
+ assertTrue(view.setContentAnimationRunning(true))
+
+ // Then: contractedChild, expandedChild, and headsUpChild should have setAnimationsRunning
+ // called on them.
+ verify(mockContracted).setAnimationsRunning(true)
+ verify(mockExpanded).setAnimationsRunning(true)
+ verify(mockHeadsUp).setAnimationsRunning(true)
+
+ // When: we set content animation running false, the state changes, so the function
+ // returns true.
+ assertTrue(view.setContentAnimationRunning(false))
+
+ // Then: the children have their animations stopped.
+ verify(mockContracted).setAnimationsRunning(false)
+ verify(mockExpanded).setAnimationsRunning(false)
+ verify(mockHeadsUp).setAnimationsRunning(false)
+ }
+
+ @Test
+ fun onSetAnimationInitStopped() {
+ // Given: contractedWrapper, expandedWrapper, and headsUpWrapper being set
+ val mockContracted = mock<NotificationViewWrapper>()
+ val mockExpanded = mock<NotificationViewWrapper>()
+ val mockHeadsUp = mock<NotificationViewWrapper>()
+
+ view.setContractedWrapper(mockContracted)
+ view.setExpandedWrapper(mockExpanded)
+ view.setHeadsUpWrapper(mockHeadsUp)
+
+ // When: we try to stop the animations before they've been started.
+ assertFalse(view.setContentAnimationRunning(false))
+
+ // Then: the children should not have setAnimationRunning called on them again.
+ verify(mockContracted, never()).setAnimationsRunning(false)
+ verify(mockExpanded, never()).setAnimationsRunning(false)
+ verify(mockHeadsUp, never()).setAnimationsRunning(false)
+ }
+
private fun createMockContainingNotification(notificationEntry: NotificationEntry) =
mock<ExpandableNotificationRow>().apply {
whenever(this.entry).thenReturn(notificationEntry)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 59d4720..e6f6a8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -53,6 +53,7 @@
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.util.MediaFeatureFlag;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -130,6 +131,7 @@
public final OnUserInteractionCallback mOnUserInteractionCallback;
public final Runnable mFutureDismissalRunnable;
private @InflationFlag int mDefaultInflationFlags;
+ private FeatureFlags mFeatureFlags;
public NotificationTestHelper(
Context context,
@@ -191,12 +193,17 @@
mFutureDismissalRunnable = mock(Runnable.class);
when(mOnUserInteractionCallback.registerFutureDismissal(any(), anyInt()))
.thenReturn(mFutureDismissalRunnable);
+ mFeatureFlags = mock(FeatureFlags.class);
}
public void setDefaultInflationFlags(@InflationFlag int defaultInflationFlags) {
mDefaultInflationFlags = defaultInflationFlags;
}
+ public void setFeatureFlags(FeatureFlags featureFlags) {
+ mFeatureFlags = featureFlags;
+ }
+
public ExpandableNotificationRowLogger getMockLogger() {
return mMockLogger;
}
@@ -559,7 +566,8 @@
mock(NotificationGutsManager.class),
mock(MetricsLogger.class),
mock(SmartReplyConstants.class),
- mock(SmartReplyController.class));
+ mock(SmartReplyController.class),
+ mFeatureFlags);
row.setAboveShelfChangedListener(aboveShelf -> { });
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java
index 509ba41..8f88501 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigPictureTemplateViewWrapperTest.java
@@ -16,11 +16,12 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
import android.app.Notification;
-import android.content.Context;
+import android.graphics.drawable.AnimatedImageDrawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.testing.AndroidTestingRunner;
@@ -28,11 +29,11 @@
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.TextView;
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
+import com.android.internal.widget.BigPictureNotificationImageView;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -73,4 +74,38 @@
Notification.EXTRA_LARGE_ICON_BIG, new Bundle());
wrapper.onContentUpdated(mRow);
}
+
+ @Test
+ public void setAnimationsRunning_Run() {
+ BigPictureNotificationImageView imageView = mView.findViewById(R.id.big_picture);
+ AnimatedImageDrawable mockDrawable = mock(AnimatedImageDrawable.class);
+
+ assertNotNull(imageView);
+ imageView.setImageDrawable(mockDrawable);
+
+ NotificationViewWrapper wrapper = new NotificationBigPictureTemplateViewWrapper(mContext,
+ mView, mRow);
+ // Required to re-initialize the imageView to the imageView created above.
+ wrapper.onContentUpdated(mRow);
+
+ wrapper.setAnimationsRunning(true);
+ verify(mockDrawable).start();
+ }
+
+ @Test
+ public void setAnimationsRunning_Stop() {
+ BigPictureNotificationImageView imageView = mView.findViewById(R.id.big_picture);
+ AnimatedImageDrawable mockDrawable = mock(AnimatedImageDrawable.class);
+
+ assertNotNull(imageView);
+ imageView.setImageDrawable(mockDrawable);
+
+ NotificationViewWrapper wrapper = new NotificationBigPictureTemplateViewWrapper(mContext,
+ mView, mRow);
+ // Required to re-initialize the imageView to the imageView created above.
+ wrapper.onContentUpdated(mRow);
+
+ wrapper.setAnimationsRunning(false);
+ verify(mockDrawable).stop();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt
new file mode 100644
index 0000000..3fa68bb
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapperTest.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper
+
+import android.graphics.drawable.AnimatedImageDrawable
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.R
+import com.android.internal.widget.CachingIconView
+import com.android.internal.widget.ConversationLayout
+import com.android.internal.widget.MessagingGroup
+import com.android.internal.widget.MessagingImageMessage
+import com.android.internal.widget.MessagingLinearLayout
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper
+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
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotificationConversationTemplateViewWrapperTest : SysuiTestCase() {
+
+ private lateinit var mRow: ExpandableNotificationRow
+ private lateinit var helper: NotificationTestHelper
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ helper = NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
+ mRow = helper.createRow()
+ }
+
+ @Test
+ fun setAnimationsRunning_Run() {
+ // Creates a mocked out NotificationEntry of ConversationLayout type,
+ // with a mock imageMessage.drawable embedded in its MessagingImageMessages
+ // (both top level, and in a group).
+ val mockDrawable = mock<AnimatedImageDrawable>()
+ val mockDrawable2 = mock<AnimatedImageDrawable>()
+ val mockLayoutView: View = fakeConversationLayout(mockDrawable, mockDrawable2)
+
+ val wrapper: NotificationViewWrapper =
+ NotificationConversationTemplateViewWrapper(mContext, mockLayoutView, mRow)
+ wrapper.onContentUpdated(mRow)
+ wrapper.setAnimationsRunning(true)
+
+ // Verifies that each AnimatedImageDrawable is started animating.
+ verify(mockDrawable).start()
+ verify(mockDrawable2).start()
+ }
+
+ @Test
+ fun setAnimationsRunning_Stop() {
+ // Creates a mocked out NotificationEntry of ConversationLayout type,
+ // with a mock imageMessage.drawable embedded in its MessagingImageMessages
+ // (both top level, and in a group).
+ val mockDrawable = mock<AnimatedImageDrawable>()
+ val mockDrawable2 = mock<AnimatedImageDrawable>()
+ val mockLayoutView: View = fakeConversationLayout(mockDrawable, mockDrawable2)
+
+ val wrapper: NotificationViewWrapper =
+ NotificationConversationTemplateViewWrapper(mContext, mockLayoutView, mRow)
+ wrapper.onContentUpdated(mRow)
+ wrapper.setAnimationsRunning(false)
+
+ // Verifies that each AnimatedImageDrawable is started animating.
+ verify(mockDrawable).stop()
+ verify(mockDrawable2).stop()
+ }
+
+ private fun fakeConversationLayout(
+ mockDrawableGroupMessage: AnimatedImageDrawable,
+ mockDrawableImageMessage: AnimatedImageDrawable
+ ): View {
+ val mockMessagingImageMessage: MessagingImageMessage =
+ mock<MessagingImageMessage>().apply {
+ whenever(drawable).thenReturn(mockDrawableImageMessage)
+ }
+ val mockImageMessageContainer: MessagingLinearLayout =
+ mock<MessagingLinearLayout>().apply {
+ whenever(childCount).thenReturn(1)
+ whenever(getChildAt(any())).thenReturn(mockMessagingImageMessage)
+ }
+
+ val mockMessagingImageMessageForGroup: MessagingImageMessage =
+ mock<MessagingImageMessage>().apply {
+ whenever(drawable).thenReturn(mockDrawableGroupMessage)
+ }
+ val mockMessageContainer: MessagingLinearLayout =
+ mock<MessagingLinearLayout>().apply {
+ whenever(childCount).thenReturn(1)
+ whenever(getChildAt(any())).thenReturn(mockMessagingImageMessageForGroup)
+ }
+ val mockGroup: MessagingGroup =
+ mock<MessagingGroup>().apply {
+ whenever(messageContainer).thenReturn(mockMessageContainer)
+ }
+ val mockView: View =
+ mock<ConversationLayout>().apply {
+ whenever(messagingGroups).thenReturn(ArrayList<MessagingGroup>(listOf(mockGroup)))
+ whenever(imageMessageContainer).thenReturn(mockImageMessageContainer)
+ whenever(messagingLinearLayout).thenReturn(mockMessageContainer)
+
+ // These must be mocked as they're required to be nonnull.
+ whenever(requireViewById<View>(R.id.conversation_icon_container)).thenReturn(mock())
+ whenever(requireViewById<CachingIconView>(R.id.conversation_icon))
+ .thenReturn(mock())
+ whenever(findViewById<CachingIconView>(R.id.icon)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.conversation_icon_badge_bg)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.expand_button)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.expand_button_container)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.conversation_icon_badge_ring))
+ .thenReturn(mock())
+ whenever(requireViewById<View>(R.id.app_name_text)).thenReturn(mock())
+ whenever(requireViewById<View>(R.id.conversation_text)).thenReturn(mock())
+ }
+ return mockView
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapperTest.kt
new file mode 100644
index 0000000..c0444b5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapperTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper
+
+import android.graphics.drawable.AnimatedImageDrawable
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.MessagingGroup
+import com.android.internal.widget.MessagingImageMessage
+import com.android.internal.widget.MessagingLayout
+import com.android.internal.widget.MessagingLinearLayout
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.row.NotificationTestHelper
+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
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotificationMessagingTemplateViewWrapperTest : SysuiTestCase() {
+
+ private lateinit var mRow: ExpandableNotificationRow
+ private lateinit var helper: NotificationTestHelper
+
+ @Before
+ fun setUp() {
+ allowTestableLooperAsMainThread()
+ helper = NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
+ mRow = helper.createRow()
+ }
+
+ @Test
+ fun setAnimationsRunning_Run() {
+ // Creates a mocked out NotificationEntry of MessagingLayout/MessagingStyle type,
+ // with a mock imageMessage.drawable embedded in its MessagingImageMessage.
+ val mockDrawable = mock<AnimatedImageDrawable>()
+ val mockLayoutView: View = fakeMessagingLayout(mockDrawable)
+
+ val wrapper: NotificationViewWrapper =
+ NotificationMessagingTemplateViewWrapper(mContext, mockLayoutView, mRow)
+ wrapper.setAnimationsRunning(true)
+
+ // Verifies that each AnimatedImageDrawable is started animating.
+ verify(mockDrawable).start()
+ }
+
+ @Test
+ fun setAnimationsRunning_Stop() {
+ // Creates a mocked out NotificationEntry of MessagingLayout/MessagingStyle type,
+ // with a mock imageMessage.drawable embedded in its MessagingImageMessage.
+ val mockDrawable = mock<AnimatedImageDrawable>()
+ val mockLayoutView: View = fakeMessagingLayout(mockDrawable)
+
+ val wrapper: NotificationViewWrapper =
+ NotificationMessagingTemplateViewWrapper(mContext, mockLayoutView, mRow)
+ wrapper.setAnimationsRunning(false)
+
+ // Verifies that each AnimatedImageDrawable is started animating.
+ verify(mockDrawable).stop()
+ }
+
+ private fun fakeMessagingLayout(mockDrawable: AnimatedImageDrawable): View {
+ val mockMessagingImageMessage: MessagingImageMessage =
+ mock<MessagingImageMessage>().apply { whenever(drawable).thenReturn(mockDrawable) }
+ val mockMessageContainer: MessagingLinearLayout =
+ mock<MessagingLinearLayout>().apply {
+ whenever(childCount).thenReturn(1)
+ whenever(getChildAt(any())).thenReturn(mockMessagingImageMessage)
+ }
+ val mockGroup: MessagingGroup =
+ mock<MessagingGroup>().apply {
+ whenever(messageContainer).thenReturn(mockMessageContainer)
+ }
+ val mockView: View =
+ mock<MessagingLayout>().apply {
+ whenever(messagingGroups).thenReturn(ArrayList<MessagingGroup>(listOf(mockGroup)))
+ }
+ return mockView
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 645052f..9f6f082 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -21,6 +21,7 @@
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -65,6 +66,7 @@
import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl;
import com.android.systemui.statusbar.notification.collection.provider.VisibilityLocationProviderDelegator;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifStats;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -78,6 +80,7 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -135,10 +138,14 @@
@Mock private ShadeTransitionController mShadeTransitionController;
@Mock private FeatureFlags mFeatureFlags;
@Mock private NotificationTargetsHelper mNotificationTargetsHelper;
+ @Mock private SecureSettings mSecureSettings;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
+ private final SeenNotificationsProviderImpl mSeenNotificationsProvider =
+ new SeenNotificationsProviderImpl();
+
private NotificationStackScrollLayoutController mController;
@Before
@@ -180,14 +187,15 @@
mUiEventLogger,
mRemoteInputManager,
mVisibilityLocationProviderDelegator,
- new SeenNotificationsProviderImpl(),
+ mSeenNotificationsProvider,
mShadeController,
mJankMonitor,
mStackLogger,
mLogger,
mNotificationStackSizeCalculator,
mFeatureFlags,
- mNotificationTargetsHelper
+ mNotificationTargetsHelper,
+ mSecureSettings
);
when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true);
@@ -233,16 +241,14 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ true,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ true);
setupShowEmptyShadeViewState(false);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ false,
- /* notifVisibleInShade= */ true,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ true);
}
@Test
@@ -255,16 +261,14 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ false);
setupShowEmptyShadeViewState(false);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ false,
- /* notifVisibleInShade= */ false,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ false);
}
@Test
@@ -283,16 +287,14 @@
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ false);
mController.setQsFullScreen(true);
reset(mNotificationStackScrollLayout);
mController.updateShowEmptyShadeView();
verify(mNotificationStackScrollLayout).updateEmptyShadeView(
/* visible= */ true,
- /* notifVisibleInShade= */ false,
- /* areSeenNotifsFiltered= */false);
+ /* notifVisibleInShade= */ false);
}
@Test
@@ -400,6 +402,17 @@
verify(mNotificationStackScrollLayout).setIsRemoteInputActive(true);
}
+ @Test
+ public void testSetNotifStats_updatesHasFilteredOutSeenNotifications() {
+ when(mNotifPipelineFlags.getShouldFilterUnseenNotifsOnKeyguard()).thenReturn(true);
+ mSeenNotificationsProvider.setHasFilteredOutSeenNotifications(true);
+ mController.attach(mNotificationStackScrollLayout);
+ mController.getNotifStackController().setNotifStats(NotifStats.getEmpty());
+ verify(mNotificationStackScrollLayout).setHasFilteredOutSeenNotifications(true);
+ verify(mNotificationStackScrollLayout).updateFooter();
+ verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
+ }
+
private LogMaker logMatcher(int category, int type) {
return argThat(new LogMatcher(category, type));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 7622549..dd7143a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -30,6 +30,7 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
+import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -53,6 +54,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
@@ -328,7 +330,7 @@
public void updateEmptyView_dndSuppressing() {
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, true, false);
+ mStackScroller.updateEmptyShadeView(true, true);
verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
}
@@ -338,7 +340,7 @@
mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, false, false);
+ mStackScroller.updateEmptyShadeView(true, false);
verify(mEmptyShadeView).setText(R.string.empty_shade_text);
}
@@ -347,10 +349,10 @@
public void updateEmptyView_noNotificationsToDndSuppressing() {
mStackScroller.setEmptyShadeView(mEmptyShadeView);
when(mEmptyShadeView.willBeGone()).thenReturn(true);
- mStackScroller.updateEmptyShadeView(true, false, false);
+ mStackScroller.updateEmptyShadeView(true, false);
verify(mEmptyShadeView).setText(R.string.empty_shade_text);
- mStackScroller.updateEmptyShadeView(true, true, false);
+ mStackScroller.updateEmptyShadeView(true, true);
verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
}
@@ -818,6 +820,29 @@
assertEquals(0f, mAmbientState.getStackY());
}
+ @Test
+ public void hasFilteredOutSeenNotifs_updateFooter() {
+ mStackScroller.setCurrentUserSetup(true);
+
+ // add footer
+ mStackScroller.inflateFooterView();
+ TextView footerLabel =
+ mStackScroller.mFooterView.requireViewById(R.id.unlock_prompt_footer);
+
+ mStackScroller.setHasFilteredOutSeenNotifications(true);
+ mStackScroller.updateFooter();
+
+ assertThat(footerLabel.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void hasFilteredOutSeenNotifs_updateEmptyShadeView() {
+ mStackScroller.setHasFilteredOutSeenNotifications(true);
+ mStackScroller.updateEmptyShadeView(true, false);
+
+ verify(mEmptyShadeView).setFooterText(not(0));
+ }
+
private void setBarStateForTest(int state) {
// Can't inject this through the listener or we end up on the actual implementation
// rather than the mock because the spy just coppied the anonymous inner /shruggie.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
index c17c5b0..6fc60f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java
@@ -25,8 +25,10 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.os.Vibrator;
import android.testing.AndroidTestingRunner;
import android.view.WindowInsets;
@@ -41,6 +43,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -88,6 +91,7 @@
@Mock private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
@Mock private SystemBarAttributesListener mSystemBarAttributesListener;
@Mock private Lazy<CameraLauncher> mCameraLauncherLazy;
+ @Mock private UserTracker mUserTracker;
CentralSurfacesCommandQueueCallbacks mSbcqCallbacks;
@@ -120,8 +124,11 @@
new DisableFlagsLogger(),
DEFAULT_DISPLAY,
mSystemBarAttributesListener,
- mCameraLauncherLazy);
+ mCameraLauncherLazy,
+ mUserTracker);
+ when(mUserTracker.getUserHandle()).thenReturn(
+ UserHandle.of(ActivityManager.getCurrentUser()));
when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
when(mRemoteInputQuickSettingsDisabler.adjustDisableFlags(anyInt()))
.thenAnswer((Answer<Integer>) invocation -> invocation.getArgument(0));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 4c1b219..b1363a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -44,6 +44,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.IWallpaperManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -118,6 +119,7 @@
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.shade.CameraLauncher;
import com.android.systemui.shade.NotificationPanelView;
@@ -306,6 +308,7 @@
*/
@Mock private ViewRootImpl mViewRootImpl;
@Mock private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
+ @Mock private UserTracker mUserTracker;
@Captor private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback;
@Mock IPowerManager mPowerManagerService;
@@ -321,6 +324,10 @@
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ // CentralSurfacesImpl's runtime flag check fails if the flag is absent.
+ // This value is unused, because test manifest is opted in.
+ mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
+
IThermalService thermalService = mock(IThermalService.class);
mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
Handler.createAsync(Looper.myLooper()));
@@ -338,7 +345,8 @@
new Handler(TestableLooper.get(this).getLooper()),
mock(NotifPipelineFlags.class),
mock(KeyguardNotificationVisibilityProvider.class),
- mock(UiEventLogger.class));
+ mock(UiEventLogger.class),
+ mUserTracker);
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -419,6 +427,9 @@
when(mOperatorNameViewControllerFactory.create(any()))
.thenReturn(mOperatorNameViewController);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
+ when(mUserTracker.getUserHandle()).thenReturn(
+ UserHandle.of(ActivityManager.getCurrentUser()));
mCentralSurfaces = new CentralSurfacesImpl(
mContext,
@@ -508,7 +519,8 @@
mDreamManager,
mCameraLauncherLazy,
() -> mLightRevealScrimViewModel,
- mAlternateBouncerInteractor
+ mAlternateBouncerInteractor,
+ mUserTracker
) {
@Override
protected ViewRootImpl getViewRootImpl() {
@@ -1280,7 +1292,8 @@
Handler mainHandler,
NotifPipelineFlags flags,
KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
- UiEventLogger uiEventLogger) {
+ UiEventLogger uiEventLogger,
+ UserTracker userTracker) {
super(
contentResolver,
powerManager,
@@ -1294,7 +1307,8 @@
mainHandler,
flags,
keyguardNotificationVisibilityProvider,
- uiEventLogger
+ uiEventLogger,
+ userTracker
);
mUseHeadsUp = true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index c843850..eb5edbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.res.Resources;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Handler;
@@ -44,6 +45,7 @@
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -82,6 +84,7 @@
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
+ @Mock private UserTracker mUserTracker;
@Captor private ArgumentCaptor<BatteryStateChangeCallback> mBatteryStateChangeCallback;
/**
@@ -107,6 +110,7 @@
when(mSysUIUnfoldComponent.getFoldAodAnimationController())
.thenReturn(mFoldAodAnimationController);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
mDozeParameters = new DozeParameters(
mContext,
@@ -123,7 +127,8 @@
mUnlockedScreenOffAnimationController,
mKeyguardUpdateMonitor,
mConfigurationController,
- mStatusBarStateController
+ mStatusBarStateController,
+ mUserTracker
);
verify(mBatteryController).addCallback(mBatteryStateChangeCallback.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 64dee95..305b9fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.privacy.PrivacyItemController
import com.android.systemui.privacy.logging.PrivacyLogger
import com.android.systemui.screenrecord.RecordingController
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.BluetoothController
import com.android.systemui.statusbar.policy.CastController
@@ -71,61 +72,37 @@
private const val ALARM_SLOT = "alarm"
}
- @Mock
- private lateinit var iconController: StatusBarIconController
- @Mock
- private lateinit var commandQueue: CommandQueue
- @Mock
- private lateinit var broadcastDispatcher: BroadcastDispatcher
- @Mock
- private lateinit var castController: CastController
- @Mock
- private lateinit var hotspotController: HotspotController
- @Mock
- private lateinit var bluetoothController: BluetoothController
- @Mock
- private lateinit var nextAlarmController: NextAlarmController
- @Mock
- private lateinit var userInfoController: UserInfoController
- @Mock
- private lateinit var rotationLockController: RotationLockController
- @Mock
- private lateinit var dataSaverController: DataSaverController
- @Mock
- private lateinit var zenModeController: ZenModeController
- @Mock
- private lateinit var deviceProvisionedController: DeviceProvisionedController
- @Mock
- private lateinit var keyguardStateController: KeyguardStateController
- @Mock
- private lateinit var locationController: LocationController
- @Mock
- private lateinit var sensorPrivacyController: SensorPrivacyController
- @Mock
- private lateinit var iActivityManager: IActivityManager
- @Mock
- private lateinit var alarmManager: AlarmManager
- @Mock
- private lateinit var userManager: UserManager
- @Mock
- private lateinit var devicePolicyManager: DevicePolicyManager
- @Mock
- private lateinit var recordingController: RecordingController
- @Mock
- private lateinit var telecomManager: TelecomManager
- @Mock
- private lateinit var sharedPreferences: SharedPreferences
- @Mock
- private lateinit var dateFormatUtil: DateFormatUtil
+ @Mock private lateinit var iconController: StatusBarIconController
+ @Mock private lateinit var commandQueue: CommandQueue
+ @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock private lateinit var castController: CastController
+ @Mock private lateinit var hotspotController: HotspotController
+ @Mock private lateinit var bluetoothController: BluetoothController
+ @Mock private lateinit var nextAlarmController: NextAlarmController
+ @Mock private lateinit var userInfoController: UserInfoController
+ @Mock private lateinit var rotationLockController: RotationLockController
+ @Mock private lateinit var dataSaverController: DataSaverController
+ @Mock private lateinit var zenModeController: ZenModeController
+ @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var locationController: LocationController
+ @Mock private lateinit var sensorPrivacyController: SensorPrivacyController
+ @Mock private lateinit var iActivityManager: IActivityManager
+ @Mock private lateinit var alarmManager: AlarmManager
+ @Mock private lateinit var userManager: UserManager
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock private lateinit var recordingController: RecordingController
+ @Mock private lateinit var telecomManager: TelecomManager
+ @Mock private lateinit var sharedPreferences: SharedPreferences
+ @Mock private lateinit var dateFormatUtil: DateFormatUtil
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private lateinit var ringerModeTracker: RingerModeTracker
- @Mock
- private lateinit var privacyItemController: PrivacyItemController
- @Mock
- private lateinit var privacyLogger: PrivacyLogger
+ @Mock private lateinit var privacyItemController: PrivacyItemController
+ @Mock private lateinit var privacyLogger: PrivacyLogger
@Captor
private lateinit var alarmCallbackCaptor:
- ArgumentCaptor<NextAlarmController.NextAlarmChangeCallback>
+ ArgumentCaptor<NextAlarmController.NextAlarmChangeCallback>
private lateinit var executor: FakeExecutor
private lateinit var statusBarPolicy: PhoneStatusBarPolicy
@@ -137,8 +114,8 @@
executor = FakeExecutor(FakeSystemClock())
testableLooper = TestableLooper.get(this)
context.orCreateTestableResources.addOverride(
- com.android.internal.R.string.status_bar_alarm_clock,
- ALARM_SLOT
+ com.android.internal.R.string.status_bar_alarm_clock,
+ ALARM_SLOT
)
statusBarPolicy = createStatusBarPolicy()
}
@@ -195,36 +172,37 @@
private fun createStatusBarPolicy(): PhoneStatusBarPolicy {
return PhoneStatusBarPolicy(
- iconController,
- commandQueue,
- broadcastDispatcher,
- executor,
- testableLooper.looper,
- context.resources,
- castController,
- hotspotController,
- bluetoothController,
- nextAlarmController,
- userInfoController,
- rotationLockController,
- dataSaverController,
- zenModeController,
- deviceProvisionedController,
- keyguardStateController,
- locationController,
- sensorPrivacyController,
- iActivityManager,
- alarmManager,
- userManager,
- devicePolicyManager,
- recordingController,
- telecomManager,
- /* displayId = */ 0,
- sharedPreferences,
- dateFormatUtil,
- ringerModeTracker,
- privacyItemController,
- privacyLogger
+ iconController,
+ commandQueue,
+ broadcastDispatcher,
+ executor,
+ testableLooper.looper,
+ context.resources,
+ castController,
+ hotspotController,
+ bluetoothController,
+ nextAlarmController,
+ userInfoController,
+ rotationLockController,
+ dataSaverController,
+ zenModeController,
+ deviceProvisionedController,
+ keyguardStateController,
+ locationController,
+ sensorPrivacyController,
+ iActivityManager,
+ alarmManager,
+ userManager,
+ userTracker,
+ devicePolicyManager,
+ recordingController,
+ telecomManager,
+ /* displayId = */ 0,
+ sharedPreferences,
+ dateFormatUtil,
+ ringerModeTracker,
+ privacyItemController,
+ privacyLogger
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c7a0582..c0537a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -630,6 +630,7 @@
@Test
public void transitionToUnlocked() {
+ mScrimController.setClipsQsScrim(false);
mScrimController.setRawPanelExpansionFraction(0f);
mScrimController.transitionTo(ScrimState.UNLOCKED);
finishAnimationsImmediately();
@@ -645,14 +646,21 @@
));
// Back scrim should be visible after start dragging
- mScrimController.setRawPanelExpansionFraction(0.3f);
+ mScrimController.setRawPanelExpansionFraction(0.29f);
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
mNotificationsScrim, TRANSPARENT,
mScrimBehind, SEMI_TRANSPARENT));
+ // Back scrim should be opaque at 30%
+ mScrimController.setRawPanelExpansionFraction(0.3f);
+ assertScrimAlpha(Map.of(
+ mScrimInFront, TRANSPARENT,
+ mNotificationsScrim, TRANSPARENT,
+ mScrimBehind, OPAQUE));
+
// Then, notification scrim should fade in
- mScrimController.setRawPanelExpansionFraction(0.7f);
+ mScrimController.setRawPanelExpansionFraction(0.31f);
assertScrimAlpha(Map.of(
mScrimInFront, TRANSPARENT,
mNotificationsScrim, SEMI_TRANSPARENT,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 19658e6..ccc57ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -33,6 +33,7 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -59,6 +60,7 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.ShadeControllerImpl;
@@ -139,6 +141,8 @@
private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock
private InteractionJankMonitor mJankMonitor;
+ @Mock
+ private UserTracker mUserTracker;
private final FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private ExpandableNotificationRow mNotificationRow;
private ExpandableNotificationRow mBubbleNotificationRow;
@@ -183,6 +187,8 @@
when(mVisibilityProvider.obtain(any(NotificationEntry.class), anyBoolean()))
.thenAnswer(invocation -> NotificationVisibility.obtain(
invocation.<NotificationEntry>getArgument(0).getKey(), 0, 1, false));
+ when(mUserTracker.getUserHandle()).thenReturn(
+ UserHandle.of(ActivityManager.getCurrentUser()));
HeadsUpManagerPhone headsUpManager = mock(HeadsUpManagerPhone.class);
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
@@ -222,7 +228,8 @@
mActivityLaunchAnimator,
notificationAnimationProvider,
mock(LaunchFullScreenIntentProvider.class),
- mock(FeatureFlags.class)
+ mock(FeatureFlags.class),
+ mUserTracker
);
// set up dismissKeyguardThenExecute to synchronously invoke the OnDismissAction arg
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 d30222f..711e4ac 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
@@ -50,7 +50,9 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.*
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.ArgumentMatchers.nullable
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.eq
@@ -83,7 +85,8 @@
private lateinit var notifCollectionListener: NotifCollectionListener
@Mock private lateinit var mockOngoingCallFlags: OngoingCallFlags
- @Mock private lateinit var mockSwipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler
+ @Mock private lateinit var mockSwipeStatusBarAwayGestureHandler:
+ SwipeStatusBarAwayGestureHandler
@Mock private lateinit var mockOngoingCallListener: OngoingCallListener
@Mock private lateinit var mockActivityStarter: ActivityStarter
@Mock private lateinit var mockIActivityManager: IActivityManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
index 49d4bdc..0add905e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
@@ -56,6 +57,10 @@
private val _activeMobileDataSubscriptionId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
override val activeMobileDataSubscriptionId = _activeMobileDataSubscriptionId
+ override val activeSubChangedInGroupEvent: MutableSharedFlow<Unit> = MutableSharedFlow()
+
+ private val _defaultDataSubId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
+ override val defaultDataSubId = _defaultDataSubId
private val _mobileConnectivity = MutableStateFlow(MobileConnectivityModel())
override val defaultMobileNetworkConnectivity = _mobileConnectivity
@@ -81,6 +86,10 @@
_subscriptions.value = subs
}
+ fun setDefaultDataSubId(id: Int) {
+ _defaultDataSubId.value = id
+ }
+
fun setMobileConnectivity(model: MobileConnectivityModel) {
_mobileConnectivity.value = model
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 9d16b7fe..f12d113 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -90,6 +90,14 @@
}
@Test
+ fun `connectivity - defaults to connected and validated`() =
+ testScope.runTest {
+ val connectivity = underTest.defaultMobileNetworkConnectivity.value
+ assertThat(connectivity.isConnected).isTrue()
+ assertThat(connectivity.isValidated).isTrue()
+ }
+
+ @Test
fun `network event - create new subscription`() =
testScope.runTest {
var latest: List<SubscriptionModel>? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 813b0ed..ae390a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -479,6 +479,35 @@
}
@Test
+ fun testDefaultDataSubId_updatesOnBroadcast() =
+ runBlocking(IMMEDIATE) {
+ var latest: Int? = null
+ val job = underTest.defaultDataSubId.onEach { latest = it }.launchIn(this)
+
+ fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
+ receiver.onReceive(
+ context,
+ Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
+ .putExtra(PhoneConstants.SUBSCRIPTION_KEY, SUB_2_ID)
+ )
+ }
+
+ assertThat(latest).isEqualTo(SUB_2_ID)
+
+ fakeBroadcastDispatcher.registeredReceivers.forEach { receiver ->
+ receiver.onReceive(
+ context,
+ Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
+ .putExtra(PhoneConstants.SUBSCRIPTION_KEY, SUB_1_ID)
+ )
+ }
+
+ assertThat(latest).isEqualTo(SUB_1_ID)
+
+ job.cancel()
+ }
+
+ @Test
fun mobileConnectivity_default() {
assertThat(underTest.defaultMobileNetworkConnectivity.value)
.isEqualTo(MobileConnectivityModel(isConnected = false, isValidated = false))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
index a29146b..7aeaa48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconInteractor.kt
@@ -40,6 +40,8 @@
)
)
+ override val isConnected = MutableStateFlow(true)
+
private val _iconGroup = MutableStateFlow<SignalIcon.MobileIconGroup>(TelephonyIcons.THREE_G)
override val networkTypeIconGroup = _iconGroup
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
index 1c00646..172755c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
@@ -23,6 +23,7 @@
import com.android.settingslib.SignalIcon.MobileIconGroup
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import kotlinx.coroutines.flow.MutableStateFlow
@@ -59,6 +60,9 @@
override val alwaysShowDataRatIcon = MutableStateFlow(false)
override val alwaysUseCdmaLevel = MutableStateFlow(false)
+ override val defaultDataSubId = MutableStateFlow(DEFAULT_DATA_SUB_ID)
+
+ override val defaultMobileNetworkConnectivity = MutableStateFlow(MobileConnectivityModel())
private val _defaultMobileIconMapping = MutableStateFlow(TEST_MAPPING)
override val defaultMobileIconMapping = _defaultMobileIconMapping
@@ -77,6 +81,8 @@
companion object {
val DEFAULT_ICON = TelephonyIcons.G
+ const val DEFAULT_DATA_SUB_ID = 1
+
// Use [MobileMappings] to define some simple definitions
const val THREE_G = NETWORK_TYPE_GSM
const val LTE = NETWORK_TYPE_LTE
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index e6be7f1..c42aba5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -61,8 +61,10 @@
mobileIconsInteractor.activeDataConnectionHasDataEnabled,
mobileIconsInteractor.alwaysShowDataRatIcon,
mobileIconsInteractor.alwaysUseCdmaLevel,
+ mobileIconsInteractor.defaultMobileNetworkConnectivity,
mobileIconsInteractor.defaultMobileIconMapping,
mobileIconsInteractor.defaultMobileIconGroup,
+ mobileIconsInteractor.defaultDataSubId,
mobileIconsInteractor.isDefaultConnectionFailed,
connectionRepository,
)
@@ -289,6 +291,30 @@
}
@Test
+ fun `icon group - checks default data`() =
+ runBlocking(IMMEDIATE) {
+ mobileIconsInteractor.defaultDataSubId.value = SUB_1_ID
+ connectionRepository.setConnectionInfo(
+ MobileConnectionModel(
+ resolvedNetworkType = DefaultNetworkType(mobileMappingsProxy.toIconKey(THREE_G))
+ ),
+ )
+
+ var latest: MobileIconGroup? = null
+ val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isEqualTo(TelephonyIcons.THREE_G)
+
+ // Default data sub id changes to something else
+ mobileIconsInteractor.defaultDataSubId.value = 123
+ yield()
+
+ assertThat(latest).isEqualTo(TelephonyIcons.NOT_DEFAULT_DATA)
+
+ job.cancel()
+ }
+
+ @Test
fun alwaysShowDataRatIcon_matchesParent() =
runBlocking(IMMEDIATE) {
var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index b82a584..1b62d5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -31,11 +31,13 @@
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import org.junit.After
import org.junit.Before
@@ -43,13 +45,16 @@
import org.mockito.Mock
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class MobileIconsInteractorTest : SysuiTestCase() {
private lateinit var underTest: MobileIconsInteractor
private lateinit var connectionsRepository: FakeMobileConnectionsRepository
private val userSetupRepository = FakeUserSetupRepository()
private val mobileMappingsProxy = FakeMobileMappingsProxy()
- private val scope = CoroutineScope(IMMEDIATE)
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
@@ -73,7 +78,7 @@
connectionsRepository,
carrierConfigTracker,
userSetupRepository,
- scope
+ testScope.backgroundScope,
)
}
@@ -81,7 +86,7 @@
@Test
fun filteredSubscriptions_default() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: List<SubscriptionModel>? = null
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
@@ -92,7 +97,7 @@
@Test
fun filteredSubscriptions_nonOpportunistic_updatesWithMultipleSubs() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
var latest: List<SubscriptionModel>? = null
@@ -105,7 +110,7 @@
@Test
fun filteredSubscriptions_bothOpportunistic_configFalse_showsActive_3() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_3_OPP, SUB_4_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_3_ID)
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
@@ -122,7 +127,7 @@
@Test
fun filteredSubscriptions_bothOpportunistic_configFalse_showsActive_4() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_3_OPP, SUB_4_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_4_ID)
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
@@ -139,7 +144,7 @@
@Test
fun filteredSubscriptions_oneOpportunistic_configTrue_showsPrimary_active_1() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_3_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_1_ID)
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
@@ -157,7 +162,7 @@
@Test
fun filteredSubscriptions_oneOpportunistic_configTrue_showsPrimary_nonActive_1() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_3_OPP))
connectionsRepository.setActiveMobileDataSubscriptionId(SUB_3_ID)
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
@@ -175,7 +180,7 @@
@Test
fun activeDataConnection_turnedOn() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
CONNECTION_1.setDataEnabled(true)
var latest: Boolean? = null
val job =
@@ -188,7 +193,7 @@
@Test
fun activeDataConnection_turnedOff() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
CONNECTION_1.setDataEnabled(true)
var latest: Boolean? = null
val job =
@@ -204,7 +209,7 @@
@Test
fun activeDataConnection_invalidSubId() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job =
underTest.activeDataConnectionHasDataEnabled.onEach { latest = it }.launchIn(this)
@@ -220,7 +225,7 @@
@Test
fun failedConnection_connected_validated_notFailed() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
connectionsRepository.setMobileConnectivity(MobileConnectivityModel(true, true))
@@ -233,7 +238,7 @@
@Test
fun failedConnection_notConnected_notValidated_notFailed() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
@@ -247,7 +252,7 @@
@Test
fun failedConnection_connected_notValidated_failed() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.isDefaultConnectionFailed.onEach { latest = it }.launchIn(this)
@@ -261,7 +266,7 @@
@Test
fun alwaysShowDataRatIcon_configHasTrue() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this)
@@ -277,7 +282,7 @@
@Test
fun alwaysShowDataRatIcon_configHasFalse() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.alwaysShowDataRatIcon.onEach { latest = it }.launchIn(this)
@@ -293,7 +298,7 @@
@Test
fun alwaysUseCdmaLevel_configHasTrue() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this)
@@ -309,7 +314,7 @@
@Test
fun alwaysUseCdmaLevel_configHasFalse() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
var latest: Boolean? = null
val job = underTest.alwaysUseCdmaLevel.onEach { latest = it }.launchIn(this)
@@ -323,8 +328,286 @@
job.cancel()
}
+ @Test
+ fun `default mobile connectivity - uses repo value`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ var expected = MobileConnectivityModel(isConnected = true, isValidated = true)
+ connectionsRepository.setMobileConnectivity(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ expected = MobileConnectivityModel(isConnected = false, isValidated = true)
+ connectionsRepository.setMobileConnectivity(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ expected = MobileConnectivityModel(isConnected = true, isValidated = false)
+ connectionsRepository.setMobileConnectivity(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ expected = MobileConnectivityModel(isConnected = false, isValidated = false)
+ connectionsRepository.setMobileConnectivity(expected)
+ assertThat(latest).isEqualTo(expected)
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - in same group - validated matches previous value`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = true,
+ )
+ )
+ // Trigger a data change in the same subscription group
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = true,
+ )
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - in same group - validated matches previous value - expires after 2s`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = true,
+ )
+ )
+ // Trigger a data change in the same subscription group
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+ // After 1s, the force validation bit is still present
+ advanceTimeBy(1000)
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = true,
+ )
+ )
+
+ // After 2s, the force validation expires
+ advanceTimeBy(1001)
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - in same group - not validated - uses new value immediately`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = false,
+ )
+ )
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - lose validation - then switch happens - clears forced bit`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ // GIVEN the network starts validated
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = true,
+ )
+ )
+
+ // WHEN a data change happens in the same group
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+
+ // WHEN the validation bit is lost
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ // WHEN another data change happens in the same group
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+
+ // THEN the forced validation bit is still removed after 2s
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = true,
+ )
+ )
+
+ advanceTimeBy(1000)
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = true,
+ )
+ )
+
+ advanceTimeBy(1001)
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - while already forcing validation - resets clock`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = true,
+ )
+ )
+
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+
+ advanceTimeBy(1000)
+
+ // WHEN another change in same group event happens
+ connectionsRepository.activeSubChangedInGroupEvent.emit(Unit)
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ // THEN the forced validation remains for exactly 2 more seconds from now
+
+ // 1.500s from second event
+ advanceTimeBy(1500)
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = true,
+ )
+ )
+
+ // 2.001s from the second event
+ advanceTimeBy(501)
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ job.cancel()
+ }
+
+ @Test
+ fun `data switch - not in same group - uses new values`() =
+ testScope.runTest {
+ var latest: MobileConnectivityModel? = null
+ val job =
+ underTest.defaultMobileNetworkConnectivity.onEach { latest = it }.launchIn(this)
+
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = true,
+ isValidated = true,
+ )
+ )
+ connectionsRepository.setMobileConnectivity(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ assertThat(latest)
+ .isEqualTo(
+ MobileConnectivityModel(
+ isConnected = false,
+ isValidated = false,
+ )
+ )
+
+ job.cancel()
+ }
+
companion object {
- private val IMMEDIATE = Dispatchers.Main.immediate
private val tableLogBuffer =
TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index 2a8d42f..a24e29ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -274,6 +274,41 @@
}
@Test
+ fun `network type - alwaysShow - shown when not connected`() =
+ testScope.runTest {
+ interactor.setIconGroup(THREE_G)
+ interactor.isConnected.value = false
+ interactor.alwaysShowDataRatIcon.value = true
+
+ var latest: Icon? = null
+ val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this)
+
+ val expected =
+ Icon.Resource(
+ THREE_G.dataType,
+ ContentDescription.Resource(THREE_G.dataContentDescription)
+ )
+ assertThat(latest).isEqualTo(expected)
+
+ job.cancel()
+ }
+
+ @Test
+ fun `network type - not shown when not connected`() =
+ testScope.runTest {
+ interactor.setIconGroup(THREE_G)
+ interactor.isDataConnected.value = true
+ interactor.isConnected.value = false
+
+ var latest: Icon? = null
+ val job = underTest.networkTypeIcon.onEach { latest = it }.launchIn(this)
+
+ assertThat(latest).isNull()
+
+ job.cancel()
+ }
+
+ @Test
fun roaming() =
testScope.runTest {
interactor.isRoaming.value = true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
index 99e2012..45f7df3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt
@@ -159,7 +159,7 @@
underTest.displayView(getState())
assertThat(fakeWakeLock.isHeld).isTrue()
- underTest.removeView("id", "test reason")
+ underTest.removeView(DEFAULT_ID, "test reason")
assertThat(fakeWakeLock.isHeld).isFalse()
}
@@ -175,6 +175,8 @@
@Test
fun displayView_twiceWithDifferentIds_oldViewRemovedNewViewAdded() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "name",
@@ -199,10 +201,15 @@
assertThat(windowParamsCaptor.allValues[0].title).isEqualTo("First Fake Window Title")
assertThat(windowParamsCaptor.allValues[1].title).isEqualTo("Second Fake Window Title")
verify(windowManager).removeView(viewCaptor.allValues[0])
+ // Since the controller is still storing the older view in case it'll get re-displayed
+ // later, the listener shouldn't be notified
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
fun displayView_viewDoesNotDisappearsBeforeTimeout() {
+ val listener = registerListener()
+
val state = getState()
underTest.displayView(state)
reset(windowManager)
@@ -210,10 +217,13 @@
fakeClock.advanceTime(TIMEOUT_MS - 1)
verify(windowManager, never()).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
fun displayView_viewDisappearsAfterTimeout() {
+ val listener = registerListener()
+
val state = getState()
underTest.displayView(state)
reset(windowManager)
@@ -221,10 +231,13 @@
fakeClock.advanceTime(TIMEOUT_MS + 1)
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
}
@Test
fun displayView_calledAgainBeforeTimeout_timeoutReset() {
+ val listener = registerListener()
+
// First, display the view
val state = getState()
underTest.displayView(state)
@@ -239,10 +252,13 @@
// Verify we didn't hide the view
verify(windowManager, never()).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
fun displayView_calledAgainBeforeTimeout_eventuallyTimesOut() {
+ val listener = registerListener()
+
// First, display the view
val state = getState()
underTest.displayView(state)
@@ -255,6 +271,7 @@
fakeClock.advanceTime(TIMEOUT_MS + 1)
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
}
@Test
@@ -271,25 +288,9 @@
}
@Test
- fun viewUpdatedWithNewOnViewTimeoutRunnable_newRunnableUsed() {
- var runnable1Run = false
- underTest.displayView(ViewInfo(name = "name", id = "id1", windowTitle = "1")) {
- runnable1Run = true
- }
-
- var runnable2Run = false
- underTest.displayView(ViewInfo(name = "name", id = "id1", windowTitle = "1")) {
- runnable2Run = true
- }
-
- fakeClock.advanceTime(TIMEOUT_MS + 1)
-
- assertThat(runnable1Run).isFalse()
- assertThat(runnable2Run).isTrue()
- }
-
- @Test
fun multipleViewsWithDifferentIds_moreRecentReplacesOlder() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "name",
@@ -315,10 +316,16 @@
assertThat(windowParamsCaptor.allValues[1].title).isEqualTo("Second Fake Window Title")
verify(windowManager).removeView(viewCaptor.allValues[0])
verify(configurationController, never()).removeCallback(any())
+
+ // Since the controller is still storing the older view in case it'll get re-displayed
+ // later, the listener shouldn't be notified
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
- fun multipleViewsWithDifferentIds_recentActiveViewIsDisplayed() {
+ fun multipleViewsWithDifferentIds_newViewRemoved_previousViewIsDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(ViewInfo("First name", id = "id1"))
verify(windowManager).addView(any(), any())
@@ -329,24 +336,35 @@
verify(windowManager).removeView(any())
verify(windowManager).addView(any(), any())
reset(windowManager)
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
+ // WHEN the current view is removed
underTest.removeView("id2", "test reason")
+ // THEN it's correctly removed
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly("id2")
+
+ // And the previous view is correctly added
verify(windowManager).addView(any(), any())
assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1")
assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name")
+ // WHEN the previous view times out
reset(windowManager)
fakeClock.advanceTime(TIMEOUT_MS + 1)
+ // THEN it is also removed
verify(windowManager).removeView(any())
assertThat(underTest.activeViews.size).isEqualTo(0)
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).isEqualTo(listOf("id2", "id1"))
}
@Test
fun multipleViewsWithDifferentIds_oldViewRemoved_recentViewIsDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(ViewInfo("First name", id = "id1"))
verify(windowManager).addView(any(), any())
@@ -361,7 +379,8 @@
// WHEN an old view is removed
underTest.removeView("id1", "test reason")
- // THEN we don't update anything
+ // THEN we don't update anything except the listener
+ assertThat(listener.permanentlyRemovedIds).containsExactly("id1")
verify(windowManager, never()).removeView(any())
assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2")
assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name")
@@ -372,10 +391,13 @@
verify(windowManager).removeView(any())
assertThat(underTest.activeViews.size).isEqualTo(0)
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).isEqualTo(listOf("id1", "id2"))
}
@Test
fun multipleViewsWithDifferentIds_threeDifferentViews_recentActiveViewIsDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(ViewInfo("First name", id = "id1"))
underTest.displayView(ViewInfo("Second name", id = "id2"))
underTest.displayView(ViewInfo("Third name", id = "id3"))
@@ -387,6 +409,7 @@
underTest.removeView("id3", "test reason")
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEqualTo(listOf("id3"))
assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id2")
assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name")
verify(configurationController, never()).removeCallback(any())
@@ -395,6 +418,7 @@
underTest.removeView("id2", "test reason")
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEqualTo(listOf("id3", "id2"))
assertThat(underTest.mostRecentViewInfo?.id).isEqualTo("id1")
assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("First name")
verify(configurationController, never()).removeCallback(any())
@@ -403,6 +427,7 @@
fakeClock.advanceTime(TIMEOUT_MS + 1)
verify(windowManager).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEqualTo(listOf("id3", "id2", "id1"))
assertThat(underTest.activeViews.size).isEqualTo(0)
verify(configurationController).removeCallback(any())
}
@@ -438,6 +463,8 @@
@Test
fun multipleViews_mostRecentViewRemoved_otherViewsTimedOutAndNotDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(ViewInfo("First name", id = "id1", timeoutMs = 4000))
fakeClock.advanceTime(1000)
underTest.displayView(ViewInfo("Second name", id = "id2", timeoutMs = 4000))
@@ -451,10 +478,13 @@
verify(windowManager, never()).addView(any(), any())
assertThat(underTest.activeViews.size).isEqualTo(0)
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly("id1", "id2", "id3")
}
@Test
fun multipleViews_mostRecentViewRemoved_viewWithShortTimeLeftNotDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(ViewInfo("First name", id = "id1", timeoutMs = 4000))
fakeClock.advanceTime(1000)
underTest.displayView(ViewInfo("Second name", id = "id2", timeoutMs = 2500))
@@ -467,10 +497,13 @@
verify(windowManager, never()).addView(any(), any())
assertThat(underTest.activeViews.size).isEqualTo(0)
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly("id1", "id2")
}
@Test
fun lowerThenHigherPriority_higherReplacesLower() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "normal",
@@ -499,10 +532,15 @@
verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor))
assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title")
verify(configurationController, never()).removeCallback(any())
+ // Since the controller is still storing the older view in case it'll get re-displayed
+ // later, the listener shouldn't be notified
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
fun lowerThenHigherPriority_lowerPriorityRedisplayed() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "normal",
@@ -537,6 +575,7 @@
// THEN the normal view is re-displayed
verify(windowManager).removeView(viewCaptor.allValues[1])
+ assertThat(listener.permanentlyRemovedIds).containsExactly("critical")
verify(windowManager).addView(any(), capture(windowParamsCaptor))
assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title")
verify(configurationController, never()).removeCallback(any())
@@ -544,6 +583,8 @@
@Test
fun lowerThenHigherPriority_lowerPriorityNotRedisplayedBecauseTimedOut() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "normal",
@@ -573,6 +614,7 @@
verify(windowManager, never()).addView(any(), any())
assertThat(underTest.activeViews).isEmpty()
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly("critical", "normal")
}
@Test
@@ -609,6 +651,8 @@
@Test
fun higherThenLowerPriority_lowerEventuallyDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "critical",
@@ -644,6 +688,7 @@
// THEN the second normal view is displayed
verify(windowManager).removeView(viewCaptor.value)
+ assertThat(listener.permanentlyRemovedIds).containsExactly("critical")
verify(windowManager).addView(capture(viewCaptor), capture(windowParamsCaptor))
assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title")
assertThat(underTest.activeViews.size).isEqualTo(1)
@@ -652,6 +697,8 @@
@Test
fun higherThenLowerPriority_lowerNotDisplayedBecauseTimedOut() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "critical",
@@ -691,10 +738,13 @@
verify(windowManager, never()).addView(any(), any())
assertThat(underTest.activeViews).isEmpty()
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly("critical", "normal")
}
@Test
fun criticalThenNewCritical_newCriticalDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "critical 1",
@@ -724,10 +774,15 @@
assertThat(windowParamsCaptor.value.title).isEqualTo("Critical Window Title 2")
assertThat(underTest.activeViews.size).isEqualTo(2)
verify(configurationController, never()).removeCallback(any())
+ // Since the controller is still storing the older view in case it'll get re-displayed
+ // later, the listener shouldn't be notified
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
fun normalThenNewNormal_newNormalDisplayed() {
+ val listener = registerListener()
+
underTest.displayView(
ViewInfo(
name = "normal 1",
@@ -757,6 +812,9 @@
assertThat(windowParamsCaptor.value.title).isEqualTo("Normal Window Title 2")
assertThat(underTest.activeViews.size).isEqualTo(2)
verify(configurationController, never()).removeCallback(any())
+ // Since the controller is still storing the older view in case it'll get re-displayed
+ // later, the listener shouldn't be notified
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
}
@Test
@@ -957,25 +1015,103 @@
}
@Test
- fun removeView_viewRemovedAndRemovalLogged() {
+ fun removeView_viewRemovedAndRemovalLoggedAndListenerNotified() {
+ val listener = registerListener()
+
// First, add the view
underTest.displayView(getState())
// Then, remove it
val reason = "test reason"
- val deviceId = "id"
- underTest.removeView(deviceId, reason)
+ underTest.removeView(DEFAULT_ID, reason)
verify(windowManager).removeView(any())
- verify(logger).logViewRemoval(deviceId, reason)
+ verify(logger).logViewRemoval(DEFAULT_ID, reason)
verify(configurationController).removeCallback(any())
+ assertThat(listener.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
}
@Test
- fun removeView_noAdd_viewNotRemoved() {
+ fun removeView_noAdd_viewNotRemovedAndListenerNotNotified() {
+ val listener = registerListener()
+
underTest.removeView("id", "reason")
verify(windowManager, never()).removeView(any())
+ assertThat(listener.permanentlyRemovedIds).isEmpty()
+ }
+
+ @Test
+ fun listenerRegistered_notifiedOnRemoval() {
+ val listener = registerListener()
+ underTest.displayView(getState())
+
+ underTest.removeView(DEFAULT_ID, "reason")
+
+ assertThat(listener.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
+ }
+
+ @Test
+ fun listenerRegistered_notifiedOnTimedOutEvenWhenNotDisplayed() {
+ val listener = registerListener()
+ underTest.displayView(
+ ViewInfo(
+ id = "id1",
+ name = "name1",
+ timeoutMs = 3000,
+ ),
+ )
+
+ // Display a second view
+ underTest.displayView(
+ ViewInfo(
+ id = "id2",
+ name = "name2",
+ timeoutMs = 2500,
+ ),
+ )
+
+ // WHEN the second view times out
+ fakeClock.advanceTime(2501)
+
+ // THEN the listener is notified of both IDs, since id2 timed out and id1 doesn't have
+ // enough time left to be redisplayed
+ assertThat(listener.permanentlyRemovedIds).containsExactly("id1", "id2")
+ }
+
+ @Test
+ fun multipleListeners_allNotified() {
+ val listener1 = registerListener()
+ val listener2 = registerListener()
+ val listener3 = registerListener()
+
+ underTest.displayView(getState())
+
+ underTest.removeView(DEFAULT_ID, "reason")
+
+ assertThat(listener1.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
+ assertThat(listener2.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
+ assertThat(listener3.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
+ }
+
+ @Test
+ fun sameListenerRegisteredMultipleTimes_onlyNotifiedOnce() {
+ val listener = registerListener()
+ underTest.registerListener(listener)
+ underTest.registerListener(listener)
+
+ underTest.displayView(getState())
+
+ underTest.removeView(DEFAULT_ID, "reason")
+
+ assertThat(listener.permanentlyRemovedIds).hasSize(1)
+ assertThat(listener.permanentlyRemovedIds).containsExactly(DEFAULT_ID)
+ }
+
+ private fun registerListener(): Listener {
+ return Listener().also {
+ underTest.registerListener(it)
+ }
}
private fun getState(name: String = "name") = ViewInfo(name)
@@ -1030,9 +1166,17 @@
override val windowTitle: String = "Window Title",
override val wakeReason: String = "WAKE_REASON",
override val timeoutMs: Int = TIMEOUT_MS.toInt(),
- override val id: String = "id",
+ override val id: String = DEFAULT_ID,
override val priority: ViewPriority = ViewPriority.NORMAL,
) : TemporaryViewInfo()
+
+ inner class Listener : TemporaryViewDisplayController.Listener {
+ val permanentlyRemovedIds = mutableListOf<String>()
+ override fun onInfoPermanentlyRemoved(id: String) {
+ permanentlyRemovedIds.add(id)
+ }
+ }
}
private const val TIMEOUT_MS = 10000L
+private const val DEFAULT_ID = "defaultId"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
index 90178c6..45eb1f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinatorTest.kt
@@ -20,6 +20,7 @@
import android.os.VibrationEffect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
@@ -43,6 +44,8 @@
import com.android.systemui.temporarydisplay.ViewPriority
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.view.ViewUtil
@@ -54,6 +57,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@@ -74,6 +78,7 @@
@Mock private lateinit var falsingCollector: FalsingCollector
@Mock private lateinit var viewUtil: ViewUtil
@Mock private lateinit var vibratorHelper: VibratorHelper
+ @Mock private lateinit var swipeGestureHandler: SwipeChipbarAwayGestureHandler
private lateinit var fakeWakeLockBuilder: WakeLockFake.Builder
private lateinit var fakeWakeLock: WakeLockFake
private lateinit var fakeClock: FakeSystemClock
@@ -106,6 +111,7 @@
powerManager,
falsingManager,
falsingCollector,
+ swipeGestureHandler,
viewUtil,
vibratorHelper,
fakeWakeLockBuilder,
@@ -430,17 +436,101 @@
verify(logger).logViewUpdate(eq(WINDOW_TITLE), eq("new title text"), any())
}
+ @Test
+ fun swipeToDismiss_false_neverListensForGesture() {
+ underTest.displayView(
+ createChipbarInfo(
+ Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ Text.Loaded("title text"),
+ endItem = ChipbarEndItem.Loading,
+ allowSwipeToDismiss = false,
+ )
+ )
+
+ verify(swipeGestureHandler, never()).addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun swipeToDismiss_true_listensForGesture() {
+ underTest.displayView(
+ createChipbarInfo(
+ Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ Text.Loaded("title text"),
+ endItem = ChipbarEndItem.Loading,
+ allowSwipeToDismiss = true,
+ )
+ )
+
+ verify(swipeGestureHandler).addOnGestureDetectedCallback(any(), any())
+ }
+
+ @Test
+ fun swipeToDismiss_swipeOccurs_viewDismissed() {
+ underTest.displayView(
+ createChipbarInfo(
+ Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ Text.Loaded("title text"),
+ endItem = ChipbarEndItem.Loading,
+ allowSwipeToDismiss = true,
+ )
+ )
+ val view = getChipbarView()
+
+ val callbackCaptor = argumentCaptor<(MotionEvent) -> Unit>()
+ verify(swipeGestureHandler).addOnGestureDetectedCallback(any(), capture(callbackCaptor))
+
+ callbackCaptor.value.invoke(MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0))
+
+ verify(windowManager).removeView(view)
+ }
+
+ @Test
+ fun swipeToDismiss_viewUpdatedToFalse_swipeOccurs_viewNotDismissed() {
+ underTest.displayView(
+ createChipbarInfo(
+ Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ Text.Loaded("title text"),
+ endItem = ChipbarEndItem.Loading,
+ allowSwipeToDismiss = true,
+ )
+ )
+ val view = getChipbarView()
+ val callbackCaptor = argumentCaptor<(MotionEvent) -> Unit>()
+ verify(swipeGestureHandler).addOnGestureDetectedCallback(any(), capture(callbackCaptor))
+
+ // WHEN the view is updated to not allow swipe-to-dismiss
+ underTest.displayView(
+ createChipbarInfo(
+ Icon.Resource(R.drawable.ic_cake, contentDescription = null),
+ Text.Loaded("title text"),
+ endItem = ChipbarEndItem.Loading,
+ allowSwipeToDismiss = false,
+ )
+ )
+
+ // THEN the callback is removed
+ verify(swipeGestureHandler).removeOnGestureDetectedCallback(any())
+
+ // And WHEN the old callback is invoked
+ callbackCaptor.value.invoke(MotionEvent.obtain(0L, 0L, 0, 0f, 0f, 0))
+
+ // THEN it is ignored and view isn't removed
+ verify(windowManager, never()).removeView(view)
+ }
+
private fun createChipbarInfo(
startIcon: Icon,
text: Text,
endItem: ChipbarEndItem?,
vibrationEffect: VibrationEffect? = null,
+ allowSwipeToDismiss: Boolean = false,
): ChipbarInfo {
return ChipbarInfo(
TintedIcon(startIcon, tintAttr = null),
text,
endItem,
vibrationEffect,
+ allowSwipeToDismiss,
windowTitle = WINDOW_TITLE,
wakeReason = WAKE_REASON,
timeoutMs = TIMEOUT,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt
index 4ef4e6c..ffac8f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt
@@ -43,6 +43,7 @@
powerManager: PowerManager,
falsingManager: FalsingManager,
falsingCollector: FalsingCollector,
+ swipeChipbarAwayGestureHandler: SwipeChipbarAwayGestureHandler,
viewUtil: ViewUtil,
vibratorHelper: VibratorHelper,
wakeLockBuilder: WakeLock.Builder,
@@ -59,6 +60,7 @@
powerManager,
falsingManager,
falsingCollector,
+ swipeChipbarAwayGestureHandler,
viewUtil,
vibratorHelper,
wakeLockBuilder,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt
new file mode 100644
index 0000000..a87a950
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/SwipeChipbarAwayGestureHandlerTest.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.temporarydisplay.chipbar
+
+import android.graphics.Rect
+import android.view.MotionEvent
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+
+@SmallTest
+class SwipeChipbarAwayGestureHandlerTest : SysuiTestCase() {
+
+ private lateinit var underTest: SwipeChipbarAwayGestureHandler
+
+ @Before
+ fun setUp() {
+ underTest = SwipeChipbarAwayGestureHandler(context, mock())
+ }
+
+ @Test
+ fun startOfGestureIsWithinBounds_noViewFetcher_returnsFalse() {
+ assertThat(underTest.startOfGestureIsWithinBounds(createMotionEvent())).isFalse()
+ }
+
+ @Test
+ fun startOfGestureIsWithinBounds_usesViewFetcher_aboveBottom_returnsTrue() {
+ val view = createMockView()
+
+ underTest.setViewFetcher { view }
+
+ val motionEvent = createMotionEvent(y = VIEW_BOTTOM - 100f)
+ assertThat(underTest.startOfGestureIsWithinBounds(motionEvent)).isTrue()
+ }
+
+ @Test
+ fun startOfGestureIsWithinBounds_usesViewFetcher_slightlyBelowBottom_returnsTrue() {
+ val view = createMockView()
+
+ underTest.setViewFetcher { view }
+
+ val motionEvent = createMotionEvent(y = VIEW_BOTTOM + 20f)
+ assertThat(underTest.startOfGestureIsWithinBounds(motionEvent)).isTrue()
+ }
+
+ @Test
+ fun startOfGestureIsWithinBounds_usesViewFetcher_tooFarDown_returnsFalse() {
+ val view = createMockView()
+
+ underTest.setViewFetcher { view }
+
+ val motionEvent = createMotionEvent(y = VIEW_BOTTOM * 4f)
+ assertThat(underTest.startOfGestureIsWithinBounds(motionEvent)).isFalse()
+ }
+
+ @Test
+ fun startOfGestureIsWithinBounds_viewFetcherReset_returnsFalse() {
+ val view = createMockView()
+
+ underTest.setViewFetcher { view }
+
+ val motionEvent = createMotionEvent(y = VIEW_BOTTOM - 100f)
+ assertThat(underTest.startOfGestureIsWithinBounds(motionEvent)).isTrue()
+
+ underTest.resetViewFetcher()
+ assertThat(underTest.startOfGestureIsWithinBounds(motionEvent)).isFalse()
+ }
+
+ private fun createMotionEvent(y: Float = 0f): MotionEvent {
+ return MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0f, y, 0)
+ }
+
+ private fun createMockView(): View {
+ return mock<View>().also {
+ doAnswer { invocation ->
+ val out: Rect = invocation.getArgument(0)
+ out.set(0, 0, 0, VIEW_BOTTOM)
+ null
+ }
+ .whenever(it)
+ .getBoundsOnScreen(any())
+ }
+ }
+
+ private companion object {
+ const val VIEW_BOTTOM = 455
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 2a93fff..1710709 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -172,7 +172,7 @@
verify(mDumpManager).registerDumpable(any(), any());
verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture());
verify(mSecureSettings).registerContentObserverForUser(
- eq(Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES)),
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
eq(false), mSettingsObserver.capture(), eq(UserHandle.USER_ALL)
);
}
@@ -790,15 +790,15 @@
reset(mResources);
when(mResources.getColor(eq(android.R.color.system_accent1_500), any()))
- .thenReturn(mThemeOverlayController.mColorScheme.getAccent1().get(6));
+ .thenReturn(mThemeOverlayController.mColorScheme.getAccent1().getS500());
when(mResources.getColor(eq(android.R.color.system_accent2_500), any()))
- .thenReturn(mThemeOverlayController.mColorScheme.getAccent2().get(6));
+ .thenReturn(mThemeOverlayController.mColorScheme.getAccent2().getS500());
when(mResources.getColor(eq(android.R.color.system_accent3_500), any()))
- .thenReturn(mThemeOverlayController.mColorScheme.getAccent3().get(6));
+ .thenReturn(mThemeOverlayController.mColorScheme.getAccent3().getS500());
when(mResources.getColor(eq(android.R.color.system_neutral1_500), any()))
- .thenReturn(mThemeOverlayController.mColorScheme.getNeutral1().get(6));
+ .thenReturn(mThemeOverlayController.mColorScheme.getNeutral1().getS500());
when(mResources.getColor(eq(android.R.color.system_neutral2_500), any()))
- .thenReturn(mThemeOverlayController.mColorScheme.getNeutral2().get(6));
+ .thenReturn(mThemeOverlayController.mColorScheme.getNeutral2().getS500());
// Defers event because we already have initial colors.
verify(mThemeOverlayApplier, never())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index 30c4f97..f4226bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -175,8 +175,10 @@
fold()
underTest.onScreenTurningOn({})
- underTest.onStartedWakingUp()
+ // The body of onScreenTurningOn is executed on fakeExecutor,
+ // run all pending tasks before calling the next method
fakeExecutor.runAllReady()
+ underTest.onStartedWakingUp()
verify(latencyTracker).onActionStart(any())
verify(latencyTracker).onActionCancel(any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt
index 51afbcb..2b86cfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/CreateUserActivityTest.kt
@@ -38,6 +38,7 @@
},
/* activityManager = */ mock(),
/* activityStarter = */ mock(),
+ mock(),
)
@get:Rule val activityRule = ActivityScenarioRule(CreateUserActivityTestable::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
index 6bfc2f1..7d0d57b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
@@ -19,9 +19,12 @@
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -35,6 +38,10 @@
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.yield
import org.junit.Test
import org.junit.runner.RunWith
@@ -231,6 +238,170 @@
}
}
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ThrottleFlowTest : SysuiTestCase() {
+
+ @Test
+ fun doesNotAffectEmissions_whenDelayAtLeastEqualToPeriod() = runTest {
+ // Arrange
+ val choreographer = createChoreographer(this)
+ val output = mutableListOf<Int>()
+ val collectJob = backgroundScope.launch {
+ flow {
+ emit(1)
+ delay(1000)
+ emit(2)
+ }.throttle(1000, choreographer.fakeClock).toList(output)
+ }
+
+ // Act
+ choreographer.advanceAndRun(0)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(999)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(1)
+
+ // Assert
+ assertThat(output).containsExactly(1, 2)
+
+ // Cleanup
+ collectJob.cancel()
+ }
+
+ @Test
+ fun delaysEmissions_withShorterThanPeriodDelay_untilPeriodElapses() = runTest {
+ // Arrange
+ val choreographer = createChoreographer(this)
+ val output = mutableListOf<Int>()
+ val collectJob = backgroundScope.launch {
+ flow {
+ emit(1)
+ delay(500)
+ emit(2)
+ }.throttle(1000, choreographer.fakeClock).toList(output)
+ }
+
+ // Act
+ choreographer.advanceAndRun(0)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(500)
+ choreographer.advanceAndRun(499)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(1)
+
+ // Assert
+ assertThat(output).containsExactly(1, 2)
+
+ // Cleanup
+ collectJob.cancel()
+ }
+
+ @Test
+ fun filtersAllButLastEmission_whenMultipleEmissionsInPeriod() = runTest {
+ // Arrange
+ val choreographer = createChoreographer(this)
+ val output = mutableListOf<Int>()
+ val collectJob = backgroundScope.launch {
+ flow {
+ emit(1)
+ delay(500)
+ emit(2)
+ delay(500)
+ emit(3)
+ }.throttle(1000, choreographer.fakeClock).toList(output)
+ }
+
+ // Act
+ choreographer.advanceAndRun(0)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(500)
+ choreographer.advanceAndRun(499)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(1)
+
+ // Assert
+ assertThat(output).containsExactly(1, 3)
+
+ // Cleanup
+ collectJob.cancel()
+ }
+
+ @Test
+ fun filtersAllButLastEmission_andDelaysIt_whenMultipleEmissionsInShorterThanPeriod() = runTest {
+ // Arrange
+ val choreographer = createChoreographer(this)
+ val output = mutableListOf<Int>()
+ val collectJob = backgroundScope.launch {
+ flow {
+ emit(1)
+ delay(500)
+ emit(2)
+ delay(250)
+ emit(3)
+ }.throttle(1000, choreographer.fakeClock).toList(output)
+ }
+
+ // Act
+ choreographer.advanceAndRun(0)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(500)
+ choreographer.advanceAndRun(250)
+ choreographer.advanceAndRun(249)
+
+ // Assert
+ assertThat(output).containsExactly(1)
+
+ // Act
+ choreographer.advanceAndRun(1)
+
+ // Assert
+ assertThat(output).containsExactly(1, 3)
+
+ // Cleanup
+ collectJob.cancel()
+ }
+
+ private fun createChoreographer(testScope: TestScope) = object {
+ val fakeClock = FakeSystemClock()
+
+ fun advanceAndRun(millis: Long) {
+ fakeClock.advanceTime(millis)
+ testScope.advanceTimeBy(millis)
+ testScope.runCurrent()
+ }
+ }
+}
+
private fun <T> assertThatFlow(flow: Flow<T>) =
object {
suspend fun emitsExactly(vararg emissions: T) =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
index d0420f7..729168a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/leak/LeakReporterTest.java
@@ -22,13 +22,17 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.NotificationManager;
+import android.os.UserHandle;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import org.junit.After;
import org.junit.Before;
@@ -48,6 +52,7 @@
private File mLeakDir;
private File mLeakDump;
private File mLeakHprof;
+ private UserTracker mUserTracker;
private NotificationManager mNotificationManager;
@Before
@@ -56,6 +61,9 @@
mLeakDump = new File(mLeakDir, LeakReporter.LEAK_DUMP);
mLeakHprof = new File(mLeakDir, LeakReporter.LEAK_HPROF);
+ mUserTracker = mock(UserTracker.class);
+ when(mUserTracker.getUserHandle()).thenReturn(
+ UserHandle.of(ActivityManager.getCurrentUser()));
mNotificationManager = mock(NotificationManager.class);
mContext.addMockSystemService(NotificationManager.class, mNotificationManager);
@@ -65,7 +73,7 @@
return null;
}).when(mLeakDetector).dump(any(), any());
- mLeakReporter = new LeakReporter(mContext, mLeakDetector, "test@example.com");
+ mLeakReporter = new LeakReporter(mContext, mUserTracker, mLeakDetector, "test@example.com");
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
index 915ea1a..0663004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java
@@ -48,6 +48,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.RingerModeLiveData;
import com.android.systemui.util.RingerModeTracker;
@@ -101,6 +102,8 @@
@Mock
private ActivityManager mActivityManager;
@Mock
+ private UserTracker mUserTracker;
+ @Mock
private DumpManager mDumpManager;
@@ -113,6 +116,7 @@
// Initial non-set value
when(mRingerModeLiveData.getValue()).thenReturn(-1);
when(mRingerModeInternalLiveData.getValue()).thenReturn(-1);
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
// Enable group volume adjustments
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions,
@@ -124,7 +128,7 @@
mBroadcastDispatcher, mRingerModeTracker, mThreadFactory, mAudioManager,
mNotificationManager, mVibrator, mIAudioService, mAccessibilityManager,
mPackageManager, mWakefullnessLifcycle, mCaptioningManager, mKeyguardManager,
- mActivityManager, mDumpManager, mCallback);
+ mActivityManager, mUserTracker, mDumpManager, mCallback);
mVolumeController.setEnableDialogs(true, true);
}
@@ -233,12 +237,13 @@
CaptioningManager captioningManager,
KeyguardManager keyguardManager,
ActivityManager activityManager,
+ UserTracker userTracker,
DumpManager dumpManager,
C callback) {
super(context, broadcastDispatcher, ringerModeTracker, theadFactory, audioManager,
notificationManager, optionalVibrator, iAudioService, accessibilityManager,
packageManager, wakefulnessLifecycle, captioningManager, keyguardManager,
- activityManager, dumpManager);
+ activityManager, userTracker, dumpManager);
mCallbacks = callback;
ArgumentCaptor<WakefulnessLifecycle.Observer> observerCaptor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt
new file mode 100644
index 0000000..b527861
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsControllerTest.kt
@@ -0,0 +1,243 @@
+/*
+ * 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.wallet.controller
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.service.quickaccesswallet.GetWalletCardsResponse
+import android.service.quickaccesswallet.QuickAccessWalletClient
+import android.service.quickaccesswallet.WalletCard
+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.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import java.util.ArrayList
+import kotlinx.coroutines.CoroutineScope
+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
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.isNull
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class WalletContextualSuggestionsControllerTest : SysuiTestCase() {
+
+ @Mock private lateinit var walletController: QuickAccessWalletController
+ @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
+ @Mock private lateinit var featureFlags: FeatureFlags
+ @Mock private lateinit var mockContext: Context
+ @Captor private lateinit var broadcastReceiver: ArgumentCaptor<BroadcastReceiver>
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(
+ broadcastDispatcher.broadcastFlow<List<String>?>(
+ any(),
+ isNull(),
+ any(),
+ any(),
+ any()
+ )
+ )
+ .thenCallRealMethod()
+
+ whenever(featureFlags.isEnabled(eq(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS)))
+ .thenReturn(true)
+
+ whenever(CARD_1.cardId).thenReturn(ID_1)
+ whenever(CARD_2.cardId).thenReturn(ID_2)
+ whenever(CARD_3.cardId).thenReturn(ID_3)
+ }
+
+ @Test
+ fun `state - has wallet cards - received contextual cards`() = runTest {
+ setUpWalletClient(listOf(CARD_1, CARD_2))
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verifyRegistered()
+ broadcastReceiver.value.onReceive(
+ mockContext,
+ createContextualCardsIntent(listOf(ID_1, ID_2))
+ )
+
+ assertThat(latest()).containsExactly(CARD_1, CARD_2)
+ }
+
+ @Test
+ fun `state - no wallet cards - received contextual cards`() = runTest {
+ setUpWalletClient(emptyList())
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verifyRegistered()
+ broadcastReceiver.value.onReceive(
+ mockContext,
+ createContextualCardsIntent(listOf(ID_1, ID_2))
+ )
+
+ assertThat(latest()).isEmpty()
+ }
+
+ @Test
+ fun `state - has wallet cards - no contextual cards`() = runTest {
+ setUpWalletClient(listOf(CARD_1, CARD_2))
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verifyRegistered()
+ broadcastReceiver.value.onReceive(mockContext, createContextualCardsIntent(emptyList()))
+
+ assertThat(latest()).isEmpty()
+ }
+
+ @Test
+ fun `state - wallet cards error`() = runTest {
+ setUpWalletClient(shouldFail = true)
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verifyRegistered()
+ broadcastReceiver.value.onReceive(
+ mockContext,
+ createContextualCardsIntent(listOf(ID_1, ID_2))
+ )
+
+ assertThat(latest()).isEmpty()
+ }
+
+ @Test
+ fun `state - no contextual cards extra`() = runTest {
+ setUpWalletClient(listOf(CARD_1, CARD_2))
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verifyRegistered()
+ broadcastReceiver.value.onReceive(mockContext, Intent(INTENT_NAME))
+
+ assertThat(latest()).isEmpty()
+ }
+
+ @Test
+ fun `state - has wallet cards - received contextual cards - feature disabled`() = runTest {
+ whenever(featureFlags.isEnabled(eq(Flags.ENABLE_WALLET_CONTEXTUAL_LOYALTY_CARDS)))
+ .thenReturn(false)
+ setUpWalletClient(listOf(CARD_1, CARD_2))
+ val latest =
+ collectLastValue(
+ createWalletContextualSuggestionsController(backgroundScope)
+ .contextualSuggestionCards,
+ )
+
+ runCurrent()
+ verify(broadcastDispatcher, never()).broadcastFlow(any(), isNull(), any(), any())
+ assertThat(latest()).isNull()
+ }
+
+ private fun createWalletContextualSuggestionsController(
+ scope: CoroutineScope
+ ): WalletContextualSuggestionsController {
+ return WalletContextualSuggestionsController(
+ scope,
+ walletController,
+ broadcastDispatcher,
+ featureFlags
+ )
+ }
+
+ private fun verifyRegistered() {
+ verify(broadcastDispatcher)
+ .registerReceiver(capture(broadcastReceiver), any(), isNull(), isNull(), any(), any())
+ }
+
+ private fun createContextualCardsIntent(
+ ids: List<String> = emptyList(),
+ ): Intent {
+ val intent = Intent(INTENT_NAME)
+ intent.putStringArrayListExtra("cardIds", ArrayList(ids))
+ return intent
+ }
+
+ private fun setUpWalletClient(
+ cards: List<WalletCard> = emptyList(),
+ shouldFail: Boolean = false
+ ) {
+ whenever(walletController.queryWalletCards(any())).thenAnswer { invocation ->
+ with(
+ invocation.arguments[0] as QuickAccessWalletClient.OnWalletCardsRetrievedCallback
+ ) {
+ if (shouldFail) {
+ onWalletCardRetrievalError(mock())
+ } else {
+ onWalletCardsRetrieved(GetWalletCardsResponse(cards, 0))
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val ID_1: String = "123"
+ private val CARD_1: WalletCard = mock()
+ private const val ID_2: String = "456"
+ private val CARD_2: WalletCard = mock()
+ private const val ID_3: String = "789"
+ private val CARD_3: WalletCard = mock()
+ private val INTENT_NAME: String = "WalletSuggestionsIntent"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
index 0fdcb95..31cce4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java
@@ -32,13 +32,13 @@
import static org.mockito.Mockito.when;
import static org.mockito.hamcrest.MockitoHamcrest.intThat;
+import android.app.ActivityManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
-import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Surface;
@@ -49,6 +49,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -81,6 +82,8 @@
private Surface mSurface;
@Mock
private Context mMockContext;
+ @Mock
+ private UserTracker mUserTracker;
@Mock
private Bitmap mWallpaperBitmap;
@@ -108,13 +111,16 @@
when(mWallpaperBitmap.getConfig()).thenReturn(Bitmap.Config.ARGB_8888);
// set up wallpaper manager
- when(mWallpaperManager.getBitmapAsUser(eq(UserHandle.USER_CURRENT), anyBoolean()))
+ when(mWallpaperManager.getBitmapAsUser(eq(ActivityManager.getCurrentUser()), anyBoolean()))
.thenReturn(mWallpaperBitmap);
when(mMockContext.getSystemService(WallpaperManager.class)).thenReturn(mWallpaperManager);
// set up surface
when(mSurfaceHolder.getSurface()).thenReturn(mSurface);
doNothing().when(mSurface).hwuiDestroy();
+
+ // set up UserTracker
+ when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser());
}
@Test
@@ -170,7 +176,7 @@
}
private ImageWallpaper createImageWallpaper() {
- return new ImageWallpaper(mFakeBackgroundExecutor) {
+ return new ImageWallpaper(mFakeBackgroundExecutor, mUserTracker) {
@Override
public Engine onCreateEngine() {
return new CanvasEngine() {
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 a537848..0a1e3e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -91,6 +91,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
@@ -361,7 +362,8 @@
mock(Handler.class),
mock(NotifPipelineFlags.class),
mock(KeyguardNotificationVisibilityProvider.class),
- mock(UiEventLogger.class)
+ mock(UiEventLogger.class),
+ mock(UserTracker.class)
);
when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
mBubbleController = new TestableBubbleController(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java
index e5316bc8..ceee0bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java
@@ -24,6 +24,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptLogger;
@@ -48,7 +49,8 @@
Handler mainHandler,
NotifPipelineFlags flags,
KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
- UiEventLogger uiEventLogger) {
+ UiEventLogger uiEventLogger,
+ UserTracker userTracker) {
super(contentResolver,
powerManager,
dreamManager,
@@ -61,7 +63,8 @@
mainHandler,
flags,
keyguardNotificationVisibilityProvider,
- uiEventLogger);
+ uiEventLogger,
+ userTracker);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index bf2235a..1bab997 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -132,8 +132,10 @@
@After
public void SysuiTeardown() {
- InstrumentationRegistry.registerInstance(mRealInstrumentation,
- InstrumentationRegistry.getArguments());
+ if (mRealInstrumentation != null) {
+ InstrumentationRegistry.registerInstance(mRealInstrumentation,
+ InstrumentationRegistry.getArguments());
+ }
if (TestableLooper.get(this) != null) {
TestableLooper.get(this).processAllMessages();
// Must remove static reference to this test object to prevent leak (b/261039202)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 0dd1fc7..251014f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -67,7 +67,10 @@
_userHandle = UserHandle.of(_userId)
val copy = callbacks.toList()
- copy.forEach { it.onUserChanged(_userId, userContext) }
+ copy.forEach {
+ it.onUserChanging(_userId, userContext)
+ it.onUserChanged(_userId, userContext)
+ }
}
fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
index e660e1f2..4b97316 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.java
@@ -23,6 +23,8 @@
import android.os.UserHandle;
import android.util.Pair;
+import com.android.systemui.settings.UserTracker;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -57,6 +59,11 @@
}
@Override
+ public UserTracker getUserTracker() {
+ return null;
+ }
+
+ @Override
public void registerContentObserverForUser(Uri uri, boolean notifyDescendents,
ContentObserver settingsObserver, int userHandle) {
List<ContentObserver> observers;
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 5ee30fb7..e549b61 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -31,7 +31,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.graphics.Rect;
-import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -43,8 +42,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import java.io.File;
@@ -52,39 +49,60 @@
import java.io.FileOutputStream;
import java.io.IOException;
+/**
+ * Backs up and restores wallpaper and metadata related to it.
+ *
+ * This agent has its own package because it does full backup as opposed to SystemBackupAgent
+ * which does key/value backup.
+ *
+ * This class stages wallpaper files for backup by copying them into its own directory because of
+ * the following reasons:
+ *
+ * <ul>
+ * <li>Non-system users don't have permission to read the directory that the system stores
+ * the wallpaper files in</li>
+ * <li>{@link BackupAgent} enforces that backed up files must live inside the package's
+ * {@link Context#getFilesDir()}</li>
+ * </ul>
+ *
+ * There are 3 files to back up:
+ * <ul>
+ * <li>The "wallpaper info" file which contains metadata like the crop applied to the
+ * wallpaper or the live wallpaper component name.</li>
+ * <li>The "system" wallpaper file.</li>
+ * <li>An optional "lock" wallpaper, which is shown on the lockscreen instead of the system
+ * wallpaper if set.</li>
+ * </ul>
+ *
+ * On restore, the metadata file is parsed and {@link WallpaperManager} APIs are used to set the
+ * wallpaper. Note that if there's a live wallpaper, the live wallpaper package name will be
+ * part of the metadata file and the wallpaper will be applied when the package it's installed.
+ */
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
private static final boolean DEBUG = false;
- // NB: must be kept in sync with WallpaperManagerService but has no
- // compile-time visibility.
+ // Names of our local-data stage files
+ @VisibleForTesting
+ static final String SYSTEM_WALLPAPER_STAGE = "wallpaper-stage";
+ @VisibleForTesting
+ static final String LOCK_WALLPAPER_STAGE = "wallpaper-lock-stage";
+ @VisibleForTesting
+ static final String WALLPAPER_INFO_STAGE = "wallpaper-info-stage";
- // Target filenames within the system's wallpaper directory
- static final String WALLPAPER = "wallpaper_orig";
- static final String WALLPAPER_LOCK = "wallpaper_lock_orig";
- static final String WALLPAPER_INFO = "wallpaper_info.xml";
-
- // Names of our local-data stage files/links
- static final String IMAGE_STAGE = "wallpaper-stage";
- static final String LOCK_IMAGE_STAGE = "wallpaper-lock-stage";
- static final String INFO_STAGE = "wallpaper-info-stage";
static final String EMPTY_SENTINEL = "empty";
static final String QUOTA_SENTINEL = "quota";
- // Not-for-backup bookkeeping
+ // Shared preferences constants.
static final String PREFS_NAME = "wbprefs.xml";
static final String SYSTEM_GENERATION = "system_gen";
static final String LOCK_GENERATION = "lock_gen";
- private File mWallpaperInfo; // wallpaper metadata file
- private File mWallpaperFile; // primary wallpaper image file
- private File mLockWallpaperFile; // lock wallpaper image file
-
// If this file exists, it means we exceeded our quota last time
private File mQuotaFile;
private boolean mQuotaExceeded;
- private WallpaperManager mWm;
+ private WallpaperManager mWallpaperManager;
@Override
public void onCreate() {
@@ -92,11 +110,7 @@
Slog.v(TAG, "onCreate()");
}
- File wallpaperDir = getWallpaperDir();
- mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
- mWallpaperFile = new File(wallpaperDir, WALLPAPER);
- mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
- mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);
+ mWallpaperManager = getSystemService(WallpaperManager.class);
mQuotaFile = new File(getFilesDir(), QUOTA_SENTINEL);
mQuotaExceeded = mQuotaFile.exists();
@@ -105,111 +119,39 @@
}
}
- @VisibleForTesting
- protected File getWallpaperDir() {
- return Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
- }
-
@Override
public void onFullBackup(FullBackupDataOutput data) throws IOException {
- // To avoid data duplication and disk churn, use links as the stage.
- final File filesDir = getFilesDir();
- final File infoStage = new File(filesDir, INFO_STAGE);
- final File imageStage = new File (filesDir, IMAGE_STAGE);
- final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
- final File empty = new File (filesDir, EMPTY_SENTINEL);
-
try {
// We always back up this 'empty' file to ensure that the absence of
// storable wallpaper imagery still produces a non-empty backup data
// stream, otherwise it'd simply be ignored in preflight.
+ final File empty = new File(getFilesDir(), EMPTY_SENTINEL);
if (!empty.exists()) {
FileOutputStream touch = new FileOutputStream(empty);
touch.close();
}
backupFile(empty, data);
- SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
- final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
+ SharedPreferences sharedPrefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- final int sysGeneration =
- mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
- final int lockGeneration =
- mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
+ // Check the IDs of the wallpapers that we backed up last time. If they haven't
+ // changed, we won't re-stage them for backup and use the old staged versions to avoid
+ // disk churn.
+ final int lastSysGeneration = sharedPrefs.getInt(SYSTEM_GENERATION, /* defValue= */ -1);
+ final int lastLockGeneration = sharedPrefs.getInt(LOCK_GENERATION, /* defValue= */ -1);
+ final int sysGeneration = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
+ final int lockGeneration = mWallpaperManager.getWallpaperId(FLAG_LOCK);
final boolean sysChanged = (sysGeneration != lastSysGeneration);
final boolean lockChanged = (lockGeneration != lastLockGeneration);
- final boolean sysEligible = mWm.isWallpaperBackupEligible(FLAG_SYSTEM);
- final boolean lockEligible = mWm.isWallpaperBackupEligible(FLAG_LOCK);
-
- // There might be a latent lock wallpaper file present but unused: don't
- // include it in the backup if that's the case.
- ParcelFileDescriptor lockFd = mWm.getWallpaperFile(FLAG_LOCK, UserHandle.USER_SYSTEM);
- final boolean hasLockWallpaper = (lockFd != null);
- IoUtils.closeQuietly(lockFd);
-
if (DEBUG) {
Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
- Slog.v(TAG, "sysEligble=" + sysEligible);
- Slog.v(TAG, "lockEligible=" + lockEligible);
- Slog.v(TAG, "hasLockWallpaper=" + hasLockWallpaper);
}
- // only back up the wallpapers if we've been told they're eligible
- if (mWallpaperInfo.exists()) {
- if (sysChanged || lockChanged || !infoStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
- FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
- }
- if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
- backupFile(infoStage, data);
- } else {
- Slog.w(TAG, "Wallpaper metadata file doesn't exist: " +
- mWallpaperFile.getPath());
- }
- if (sysEligible && mWallpaperFile.exists()) {
- if (sysChanged || !imageStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
- FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
- }
- if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
- backupFile(imageStage, data);
- prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
- } else {
- Slog.w(TAG, "Not backing up wallpaper as one of conditions is not "
- + "met: sysEligible = " + sysEligible + " wallpaperFileExists = "
- + mWallpaperFile.exists());
- }
-
- // If there's no lock wallpaper, then we have nothing to add to the backup.
- if (lockGeneration == -1) {
- if (lockChanged && lockImageStage.exists()) {
- if (DEBUG) Slog.v(TAG, "Removed lock wallpaper; deleting");
- lockImageStage.delete();
- }
- Slog.d(TAG, "No lockscreen wallpaper set, add nothing to backup");
- prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
- return;
- }
-
- // Don't try to store the lock image if we overran our quota last time
- if (lockEligible && hasLockWallpaper && mLockWallpaperFile.exists() && !mQuotaExceeded) {
- if (lockChanged || !lockImageStage.exists()) {
- if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
- FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
- }
- if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
- backupFile(lockImageStage, data);
- prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
- } else {
- Slog.w(TAG, "Not backing up lockscreen wallpaper as one of conditions is not "
- + "met: lockEligible = " + lockEligible + " hasLockWallpaper = "
- + hasLockWallpaper + " lockWallpaperFileExists = "
- + mLockWallpaperFile.exists() + " quotaExceeded (last time) = "
- + mQuotaExceeded);
- }
+ backupWallpaperInfoFile(/* sysOrLockChanged= */ sysChanged || lockChanged, data);
+ backupSystemWallpaperFile(sharedPrefs, sysChanged, sysGeneration, data);
+ backupLockWallpaperFileIfItExists(sharedPrefs, lockChanged, lockGeneration, data);
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
} finally {
@@ -222,6 +164,114 @@
}
}
+ private void backupWallpaperInfoFile(boolean sysOrLockChanged, FullBackupDataOutput data)
+ throws IOException {
+ final ParcelFileDescriptor wallpaperInfoFd = mWallpaperManager.getWallpaperInfoFile();
+
+ if (wallpaperInfoFd == null) {
+ Slog.w(TAG, "Wallpaper metadata file doesn't exist");
+ return;
+ }
+
+ final File infoStage = new File(getFilesDir(), WALLPAPER_INFO_STAGE);
+
+ if (sysOrLockChanged || !infoStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
+ copyFromPfdToFileAndClosePfd(wallpaperInfoFd, infoStage);
+ }
+
+ if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
+ backupFile(infoStage, data);
+ }
+
+ private void backupSystemWallpaperFile(SharedPreferences sharedPrefs,
+ boolean sysChanged, int sysGeneration, FullBackupDataOutput data) throws IOException {
+ if (!mWallpaperManager.isWallpaperBackupEligible(FLAG_SYSTEM)) {
+ Slog.d(TAG, "System wallpaper ineligible for backup");
+ return;
+ }
+
+ final ParcelFileDescriptor systemWallpaperImageFd = mWallpaperManager.getWallpaperFile(
+ FLAG_SYSTEM,
+ /* getCropped= */ false);
+
+ if (systemWallpaperImageFd == null) {
+ Slog.w(TAG, "System wallpaper doesn't exist");
+ return;
+ }
+
+ final File imageStage = new File(getFilesDir(), SYSTEM_WALLPAPER_STAGE);
+
+ if (sysChanged || !imageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
+ copyFromPfdToFileAndClosePfd(systemWallpaperImageFd, imageStage);
+ }
+
+ if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
+ backupFile(imageStage, data);
+ sharedPrefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
+ }
+
+ private void backupLockWallpaperFileIfItExists(SharedPreferences sharedPrefs,
+ boolean lockChanged, int lockGeneration, FullBackupDataOutput data) throws IOException {
+ final File lockImageStage = new File(getFilesDir(), LOCK_WALLPAPER_STAGE);
+
+ // This means there's no lock wallpaper set by the user.
+ if (lockGeneration == -1) {
+ if (lockChanged && lockImageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "Removed lock wallpaper; deleting");
+ lockImageStage.delete();
+ }
+ Slog.d(TAG, "No lockscreen wallpaper set, add nothing to backup");
+ sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
+ return;
+ }
+
+ if (!mWallpaperManager.isWallpaperBackupEligible(FLAG_LOCK)) {
+ Slog.d(TAG, "Lock screen wallpaper ineligible for backup");
+ return;
+ }
+
+ final ParcelFileDescriptor lockWallpaperFd = mWallpaperManager.getWallpaperFile(
+ FLAG_LOCK, /* getCropped= */ false);
+
+ // If we get to this point, that means lockGeneration != -1 so there's a lock wallpaper
+ // set, but we can't find it.
+ if (lockWallpaperFd == null) {
+ Slog.w(TAG, "Lock wallpaper doesn't exist");
+ return;
+ }
+
+ if (mQuotaExceeded) {
+ Slog.w(TAG, "Not backing up lock screen wallpaper. Quota was exceeded last time");
+ return;
+ }
+
+ if (lockChanged || !lockImageStage.exists()) {
+ if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
+ copyFromPfdToFileAndClosePfd(lockWallpaperFd, lockImageStage);
+ }
+
+ if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
+ backupFile(lockImageStage, data);
+ sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
+ }
+
+ /**
+ * Copies the contents of the given {@code pfd} to the given {@code file}.
+ *
+ * All resources used in the process including the {@code pfd} will be closed.
+ */
+ private static void copyFromPfdToFileAndClosePfd(ParcelFileDescriptor pfd, File file)
+ throws IOException {
+ try (ParcelFileDescriptor.AutoCloseInputStream inputStream =
+ new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ FileOutputStream outputStream = new FileOutputStream(file)
+ ) {
+ FileUtils.copy(inputStream, outputStream);
+ }
+ }
+
@VisibleForTesting
// fullBackupFile is final, so we intercept backups here in tests.
protected void backupFile(File file, FullBackupDataOutput data) {
@@ -244,9 +294,9 @@
public void onRestoreFinished() {
Slog.v(TAG, "onRestoreFinished()");
final File filesDir = getFilesDir();
- final File infoStage = new File(filesDir, INFO_STAGE);
- final File imageStage = new File (filesDir, IMAGE_STAGE);
- final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
+ final File infoStage = new File(filesDir, WALLPAPER_INFO_STAGE);
+ final File imageStage = new File(filesDir, SYSTEM_WALLPAPER_STAGE);
+ final File lockImageStage = new File(filesDir, LOCK_WALLPAPER_STAGE);
// If we restored separate lock imagery, the system wallpaper should be
// applied as system-only; but if there's no separate lock image, make
@@ -283,11 +333,11 @@
void updateWallpaperComponent(ComponentName wpService, boolean applyToLock) throws IOException {
if (servicePackageExists(wpService)) {
Slog.i(TAG, "Using wallpaper service " + wpService);
- mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
+ mWallpaperManager.setWallpaperComponent(wpService);
if (applyToLock) {
// We have a live wallpaper and no static lock image,
// allow live wallpaper to show "through" on lock screen.
- mWm.clear(FLAG_LOCK);
+ mWallpaperManager.clear(FLAG_LOCK);
}
} else {
// If we've restored a live wallpaper, but the component doesn't exist,
@@ -311,8 +361,9 @@
Slog.i(TAG, "Got restored wallpaper; applying which=" + which
+ "; cropHint = " + cropHint);
try (FileInputStream in = new FileInputStream(stage)) {
- mWm.setStream(in, cropHint.isEmpty() ? null : cropHint, true, which);
- } finally {} // auto-closes 'in'
+ mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, true,
+ which);
+ }
}
} else {
Slog.d(TAG, "Restore data doesn't exist for file " + stage.getPath());
@@ -384,7 +435,7 @@
if (comp != null) {
final IPackageManager pm = AppGlobals.getPackageManager();
final PackageInfo info = pm.getPackageInfo(comp.getPackageName(),
- 0, UserHandle.USER_SYSTEM);
+ 0, getUserId());
return (info != null);
}
} catch (RemoteException e) {
@@ -393,16 +444,14 @@
return false;
}
- //
- // Key/value API: abstract, therefore required; but not used
- //
-
+ /** Unused Key/Value API. */
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// Intentionally blank
}
+ /** Unused Key/Value API. */
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
@@ -427,10 +476,10 @@
if (componentName.getPackageName().equals(packageName)) {
Slog.d(TAG, "Applying component " + componentName);
- mWm.setWallpaperComponent(componentName);
+ mWallpaperManager.setWallpaperComponent(componentName);
if (applyToLock) {
try {
- mWm.clear(FLAG_LOCK);
+ mWallpaperManager.clear(FLAG_LOCK);
} catch (IOException e) {
Slog.w(TAG, "Failed to apply live wallpaper to lock screen: " + e);
}
diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
index 4367075..20dd5165 100644
--- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
+++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
@@ -18,14 +18,15 @@
import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+
+import static com.android.wallpaperbackup.WallpaperBackupAgent.LOCK_WALLPAPER_STAGE;
+import static com.android.wallpaperbackup.WallpaperBackupAgent.SYSTEM_WALLPAPER_STAGE;
+import static com.android.wallpaperbackup.WallpaperBackupAgent.WALLPAPER_INFO_STAGE;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -35,43 +36,42 @@
import android.app.backup.FullBackupDataOutput;
import android.content.ComponentName;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.UserHandle;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.content.PackageMonitor;
-import com.android.wallpaperbackup.WallpaperBackupAgent;
import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
-import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
@RunWith(AndroidJUnit4.class)
public class WallpaperBackupAgentTest {
- private static final String SYSTEM_GENERATION = "system_gen";
- private static final String LOCK_GENERATION = "lock_gen";
private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package";
private static final int TEST_SYSTEM_WALLPAPER_ID = 1;
private static final int TEST_LOCK_WALLPAPER_ID = 2;
+ private static final int NO_LOCK_WALLPAPER_ID = -1;
@Mock private FullBackupDataOutput mOutput;
@Mock private WallpaperManager mWallpaperManager;
- @Mock private SharedPreferences mSharedPreferences;
- @Mock private SharedPreferences.Editor mSharedPreferenceEditor;
@Mock private Context mMockContext;
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@@ -84,14 +84,11 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEditor);
- when(mSharedPreferenceEditor.putInt(anyString(), anyInt()))
- .thenReturn(mSharedPreferenceEditor);
- doNothing().when(mSharedPreferenceEditor).apply();
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(true);
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(true);
mContext = new ContextWithServiceOverrides(ApplicationProvider.getApplicationContext());
mContext.injectSystemService(WallpaperManager.class, mWallpaperManager);
- mContext.setSharedPreferencesOverride(mSharedPreferences);
mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot());
mWallpaperBackupAgent.attach(mContext);
@@ -100,48 +97,236 @@
mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, "");
}
- @Test
- public void testOnFullBackup_withNoChanges_onlyBacksUpEmptyFile() throws IOException {
- mockBackedUpState();
- mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
-
- mWallpaperBackupAgent.onFullBackup(mOutput);
-
- assertThat(mWallpaperBackupAgent.mBackedUpFiles.size()).isEqualTo(1);
- assertThat(mWallpaperBackupAgent.mBackedUpFiles.get(0).getName()).isEqualTo("empty");
+ @After
+ public void tearDown() {
+ FileUtils.deleteContents(mContext.getFilesDir());
}
@Test
- public void testOnFullBackup_withOnlyChangedSystem_updatesTheSharedPreferences()
- throws IOException {
- mockSystemWallpaperReadyToBackUp();
- mockUnbackedUpState();
- mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
-
+ public void testOnFullBackup_backsUpEmptyFile() throws IOException {
mWallpaperBackupAgent.onFullBackup(mOutput);
- verify(mSharedPreferenceEditor).putInt(eq(SYSTEM_GENERATION), eq(TEST_SYSTEM_WALLPAPER_ID));
+ assertThat(getBackedUpFileOptional("empty").isPresent()).isTrue();
}
@Test
- public void testOnFullBackup_withLockChangedToMatchSystem_updatesTheSharedPreferences()
- throws IOException {
- mockBackedUpState();
- mockSystemWallpaperReadyToBackUp();
- mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, -1);
+ public void testOnFullBackup_noExistingInfoStage_backsUpInfoFile() throws Exception {
+ mockWallpaperInfoFileWithContents("fake info file");
mWallpaperBackupAgent.onFullBackup(mOutput);
- InOrder inOrder = inOrder(mSharedPreferenceEditor);
- inOrder.verify(mSharedPreferenceEditor)
- .putInt(eq(SYSTEM_GENERATION), eq(TEST_SYSTEM_WALLPAPER_ID));
- inOrder.verify(mSharedPreferenceEditor).apply();
- inOrder.verify(mSharedPreferenceEditor).putInt(eq(LOCK_GENERATION), eq(-1));
- inOrder.verify(mSharedPreferenceEditor).apply();
+ assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
+ "fake info file");
}
@Test
- public void updateWallpaperComponent_doesApplyLater() throws IOException {
+ public void testOnFullBackup_existingInfoStage_noChange_backsUpAlreadyStagedInfoFile()
+ throws Exception {
+ // Do a backup first so the info file is staged.
+ mockWallpaperInfoFileWithContents("old info file");
+ // Provide system and lock wallpapers but don't change them in between backups.
+ mockSystemWallpaperFileWithContents("system wallpaper");
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // This new wallpaper should be ignored since the ID of neither wallpaper changed.
+ mockWallpaperInfoFileWithContents("new info file");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
+ "old info file");
+ }
+
+ @Test
+ public void testOnFullBackup_existingInfoStage_sysChanged_backsUpNewInfoFile()
+ throws Exception {
+ // Do a backup first so the backed up system wallpaper ID is persisted to disk.
+ mockWallpaperInfoFileWithContents("old info file");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock that the user changed the system wallpaper.
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID + 1, TEST_LOCK_WALLPAPER_ID);
+ mockWallpaperInfoFileWithContents("new info file");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
+ "new info file");
+ }
+
+ @Test
+ public void testOnFullBackup_existingInfoStage_lockChanged_backsUpNewInfoFile()
+ throws Exception {
+ // Do a backup first so the backed up lock wallpaper ID is persisted to disk.
+ mockWallpaperInfoFileWithContents("old info file");
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock that the user changed the system wallpaper.
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID + 1);
+ mockWallpaperInfoFileWithContents("new info file");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
+ "new info file");
+ }
+
+ @Test
+ public void testOnFullBackup_systemWallpaperNotEligible_doesNotBackUpSystemWallpaper()
+ throws Exception {
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(false);
+ mockSystemWallpaperFileWithContents("system wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertThat(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).isPresent()).isFalse();
+ }
+
+ @Test
+ public void testOnFullBackup_existingSystemStage_noSysChange_backsUpAlreadyStagedFile()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockSystemWallpaperFileWithContents("system wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // This new file should be ignored since the ID of the wallpaper did not change.
+ mockSystemWallpaperFileWithContents("new system wallpaper");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
+ "system wallpaper");
+ }
+
+ @Test
+ public void testOnFullBackup_existingSystemStage_sysChanged_backsUpNewSystemWallpaper()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockSystemWallpaperFileWithContents("system wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock that the system wallpaper was changed by the user.
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID + 1, NO_LOCK_WALLPAPER_ID);
+ mockSystemWallpaperFileWithContents("new system wallpaper");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
+ "new system wallpaper");
+ }
+
+ @Test
+ public void testOnFullBackup_noExistingSystemStage_backsUpSystemWallpaper()
+ throws Exception {
+ mockSystemWallpaperFileWithContents("system wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
+ "system wallpaper");
+ }
+
+ @Test
+ public void testOnFullBackup_lockWallpaperNotEligible_doesNotBackUpLockWallpaper()
+ throws Exception {
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(false);
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertThat(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).isPresent()).isFalse();
+ }
+
+ @Test
+ public void testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_NotBackUpOldStage()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock the ID of the lock wallpaper to indicate it's not set.
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertThat(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).isPresent()).isFalse();
+ }
+
+ @Test
+ public void testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_deletesExistingStage()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock the ID of the lock wallpaper to indicate it's not set.
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertThat(new File(mContext.getFilesDir(), LOCK_WALLPAPER_STAGE).exists()).isFalse();
+ }
+
+ @Test
+ public void testOnFullBackup_existingLockStage_noLockChange_backsUpAlreadyStagedFile()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockLockWallpaperFileWithContents("old lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // This new file should be ignored since the ID of the wallpaper did not change.
+ mockLockWallpaperFileWithContents("new lock wallpaper");
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
+ "old lock wallpaper");
+ }
+
+ @Test
+ public void testOnFullBackup_existingLockStage_lockChanged_backsUpNewLockWallpaper()
+ throws Exception {
+ // Do a backup first so that a stage file is created.
+ mockLockWallpaperFileWithContents("old lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+ mWallpaperBackupAgent.mBackedUpFiles.clear();
+ // Mock that the lock wallpaper was changed by the user.
+ mockLockWallpaperFileWithContents("new lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID + 1);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
+ "new lock wallpaper");
+ }
+
+ @Test
+ public void testOnFullBackup_noExistingLockStage_backsUpLockWallpaper()
+ throws Exception {
+ mockLockWallpaperFileWithContents("lock wallpaper");
+ mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
+
+ mWallpaperBackupAgent.onFullBackup(mOutput);
+
+ assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
+ "lock wallpaper");
+ }
+
+ @Test
+ public void testUpdateWallpaperComponent_doesApplyLater() throws IOException {
mWallpaperBackupAgent.mIsDeviceInRestore = true;
mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
@@ -156,7 +341,7 @@
}
@Test
- public void updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen()
+ public void testUpdateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen()
throws IOException {
mWallpaperBackupAgent.mIsDeviceInRestore = true;
@@ -172,7 +357,7 @@
}
@Test
- public void updateWallpaperComponent_deviceNotInRestore_doesNotApply()
+ public void testUpdateWallpaperComponent_deviceNotInRestore_doesNotApply()
throws IOException {
mWallpaperBackupAgent.mIsDeviceInRestore = false;
@@ -188,7 +373,7 @@
}
@Test
- public void updateWallpaperComponent_differentPackageInstalled_doesNotApply()
+ public void testUpdateWallpaperComponent_differentPackageInstalled_doesNotApply()
throws IOException {
mWallpaperBackupAgent.mIsDeviceInRestore = false;
@@ -203,33 +388,48 @@
verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
}
- private void mockUnbackedUpState() {
- mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
- when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(-1);
- when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1))).thenReturn(-1);
+ private void mockCurrentWallpaperIds(int systemWallpaperId, int lockWallpaperId) {
+ when(mWallpaperManager.getWallpaperId(eq(FLAG_SYSTEM))).thenReturn(systemWallpaperId);
+ when(mWallpaperManager.getWallpaperId(eq(FLAG_LOCK))).thenReturn(lockWallpaperId);
}
- private void mockBackedUpState() {
- when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1)))
- .thenReturn(TEST_SYSTEM_WALLPAPER_ID);
- when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1)))
- .thenReturn(TEST_LOCK_WALLPAPER_ID);
+ private File createTemporaryFileWithContentString(String contents) throws Exception {
+ File file = mTemporaryFolder.newFile();
+ try (FileOutputStream outputStream = new FileOutputStream(file)) {
+ outputStream.write(contents.getBytes());
+ }
+ return file;
}
- private void mockCurrentWallpapers(int systemWallpaperId, int lockWallpaperId) {
- when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_SYSTEM), eq(UserHandle.USER_SYSTEM)))
- .thenReturn(systemWallpaperId);
- when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_LOCK), eq(UserHandle.USER_SYSTEM)))
- .thenReturn(lockWallpaperId);
- when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(true);
- when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(true);
+ private void assertFileContentEquals(File file, String expected) throws Exception {
+ try (FileInputStream inputStream = new FileInputStream(file)) {
+ assertThat(new String(inputStream.readAllBytes())).isEqualTo(expected);
+ }
}
- private void mockSystemWallpaperReadyToBackUp() throws IOException {
- // Create a system wallpaper file
- mTemporaryFolder.newFile("wallpaper_orig");
- // Create staging file to simulate he wallpaper being ready to back up
- new File(mContext.getFilesDir(), "wallpaper-stage").createNewFile();
+ private Optional<File> getBackedUpFileOptional(String fileName) {
+ return mWallpaperBackupAgent.mBackedUpFiles.stream().filter(
+ file -> file.getName().equals(fileName)).findFirst();
+ }
+
+ private void mockWallpaperInfoFileWithContents(String contents) throws Exception {
+ File fakeInfoFile = createTemporaryFileWithContentString(contents);
+ when(mWallpaperManager.getWallpaperInfoFile()).thenReturn(
+ ParcelFileDescriptor.open(fakeInfoFile, MODE_READ_ONLY));
+ }
+
+ private void mockSystemWallpaperFileWithContents(String contents) throws Exception {
+ File fakeSystemWallpaperFile = createTemporaryFileWithContentString(contents);
+ when(mWallpaperManager.getWallpaperFile(eq(FLAG_SYSTEM), /* cropped = */
+ eq(false))).thenReturn(
+ ParcelFileDescriptor.open(fakeSystemWallpaperFile, MODE_READ_ONLY));
+ }
+
+ private void mockLockWallpaperFileWithContents(String contents) throws Exception {
+ File fakeLockWallpaperFile = createTemporaryFileWithContentString(contents);
+ when(mWallpaperManager.getWallpaperFile(eq(FLAG_LOCK), /* cropped = */
+ eq(false))).thenReturn(
+ ParcelFileDescriptor.open(fakeLockWallpaperFile, MODE_READ_ONLY));
}
private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
@@ -243,21 +443,11 @@
}
@Override
- protected File getWallpaperDir() {
- return mWallpaperBaseDirectory;
- }
-
- @Override
protected void backupFile(File file, FullBackupDataOutput data) {
mBackedUpFiles.add(file);
}
@Override
- public SharedPreferences getSharedPreferences(File file, int mode) {
- return mSharedPreferences;
- }
-
- @Override
boolean servicePackageExists(ComponentName comp) {
return false;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index 3fa0ab6..e6abc4c 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -391,7 +391,7 @@
private boolean takeScreenshot() {
ScreenshotHelper screenshotHelper = (mScreenshotHelperSupplier != null)
? mScreenshotHelperSupplier.get() : new ScreenshotHelper(mContext);
- screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+ screenshotHelper.takeScreenshot(
WindowManager.ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS,
new Handler(Looper.getMainLooper()), null);
return true;
diff --git a/services/api/current.txt b/services/api/current.txt
index 3926b39..e66bf4d 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -180,8 +180,8 @@
method @Nullable public String getPrimaryCpuAbi();
method @Nullable public String getSeInfo();
method @Nullable public String getSecondaryCpuAbi();
+ method @NonNull public java.util.List<com.android.server.pm.pkg.SharedLibrary> getSharedLibraryDependencies();
method @NonNull public com.android.server.pm.pkg.PackageUserState getStateForUser(@NonNull android.os.UserHandle);
- method @NonNull public java.util.List<com.android.server.pm.pkg.SharedLibrary> getUsesLibraries();
method public boolean isApex();
method public boolean isPrivileged();
method public boolean isSystem();
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 2c8bfeb..998c9c2 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -281,6 +281,8 @@
// Pseudoname that we use for the Package Manager metadata "package".
public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
+ public static final String WALLPAPER_PACKAGE = "com.android.wallpaperbackup";
+
// Retry interval for clear/init when the transport is unavailable
private static final long TRANSPORT_RETRY_INTERVAL = 1 * AlarmManager.INTERVAL_HOUR;
@@ -309,7 +311,6 @@
private static final String SERIAL_ID_FILE = "serial_id";
private static final String SKIP_USER_FACING_PACKAGES = "backup_skip_user_facing_packages";
- private static final String WALLPAPER_PACKAGE = "com.android.wallpaperbackup";
private final @UserIdInt int mUserId;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index 7f0b56f..2ee9174 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -19,7 +19,9 @@
import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.PACKAGE_MANAGER_SENTINEL;
+import static com.android.server.backup.UserBackupManagerService.SETTINGS_PACKAGE;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import static com.android.server.backup.UserBackupManagerService.WALLPAPER_PACKAGE;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.Nullable;
@@ -55,8 +57,8 @@
public class BackupEligibilityRules {
private static final boolean DEBUG = false;
// List of system packages that are eligible for backup in non-system users.
- private static final Set<String> systemPackagesAllowedForAllUsers =
- Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME);
+ private static final Set<String> systemPackagesAllowedForAllUsers = Sets.newArraySet(
+ PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME, WALLPAPER_PACKAGE, SETTINGS_PACKAGE);
private final PackageManager mPackageManager;
private final PackageManagerInternal mPackageManagerInternal;
diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
index b04f3c5..e9cd84a 100644
--- a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
@@ -268,9 +268,9 @@
@NonNull ResultReceiver resultReceiver) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- createAssociation(userId, packageName, macAddress,
- request.getDisplayName(), request.getDeviceProfile(),
- request.getAssociatedDevice(), request.isSelfManaged(),
+ createAssociation(userId, packageName, macAddress, request.getDisplayName(),
+ request.getDeviceProfile(), request.getAssociatedDevice(),
+ request.isSelfManaged(),
callback, resultReceiver);
} finally {
Binder.restoreCallingIdentity(callingIdentity);
@@ -287,7 +287,8 @@
final AssociationInfo association = new AssociationInfo(id, userId, packageName,
macAddress, displayName, deviceProfile, associatedDevice, selfManaged,
- /* notifyOnDeviceNearby */ false, /* revoked */ false, timestamp, Long.MAX_VALUE);
+ /* notifyOnDeviceNearby */ false, /* revoked */ false, timestamp, Long.MAX_VALUE,
+ /* systemDataSyncFlags */ ~0);
if (deviceProfile != null) {
// If the "Device Profile" is specified, make the companion application a holder of the
@@ -315,6 +316,20 @@
// that there are other devices with the same profile, so the role holder won't be removed.
}
+ public void enableSystemDataSync(int associationId, int flags) {
+ AssociationInfo association = mAssociationStore.getAssociationById(associationId);
+ AssociationInfo updated = AssociationInfo.builder(association)
+ .setSystemDataSyncFlags(association.getSystemDataSyncFlags() | flags).build();
+ mAssociationStore.updateAssociation(updated);
+ }
+
+ public void disableSystemDataSync(int associationId, int flags) {
+ AssociationInfo association = mAssociationStore.getAssociationById(associationId);
+ AssociationInfo updated = AssociationInfo.builder(association)
+ .setSystemDataSyncFlags(association.getSystemDataSyncFlags() & (~flags)).build();
+ mAssociationStore.updateAssociation(updated);
+ }
+
private void addAssociationToStore(@NonNull AssociationInfo association,
@Nullable String deviceProfile) {
Slog.i(TAG, "New CDM association created=" + association);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index d34fc59..b74dfcb 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -714,6 +714,18 @@
}
@Override
+ public void enableSystemDataSync(int associationId, int flags) {
+ getAssociationWithCallerChecks(associationId);
+ mAssociationRequestsProcessor.enableSystemDataSync(associationId, flags);
+ }
+
+ @Override
+ public void disableSystemDataSync(int associationId, int flags) {
+ getAssociationWithCallerChecks(associationId);
+ mAssociationRequestsProcessor.disableSystemDataSync(associationId, flags);
+ }
+
+ @Override
public void notifyDeviceAppeared(int associationId) {
if (DEBUG) Log.i(TAG, "notifyDevice_Appeared() id=" + associationId);
@@ -1160,16 +1172,20 @@
}
NetworkPolicyManager networkPolicyManager = NetworkPolicyManager.from(getContext());
- if (containsEither(packageInfo.requestedPermissions,
- android.Manifest.permission.USE_DATA_IN_BACKGROUND,
- android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) {
- networkPolicyManager.addUidPolicy(
- packageInfo.applicationInfo.uid,
- NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
- } else {
- networkPolicyManager.removeUidPolicy(
- packageInfo.applicationInfo.uid,
- NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
+ try {
+ if (containsEither(packageInfo.requestedPermissions,
+ android.Manifest.permission.USE_DATA_IN_BACKGROUND,
+ android.Manifest.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND)) {
+ networkPolicyManager.addUidPolicy(
+ packageInfo.applicationInfo.uid,
+ NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
+ } else {
+ networkPolicyManager.removeUidPolicy(
+ packageInfo.applicationInfo.uid,
+ NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
+ }
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, e.getMessage());
}
exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid);
diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java
index a57f5a2..b66c193 100644
--- a/services/companion/java/com/android/server/companion/PersistentDataStore.java
+++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java
@@ -132,7 +132,8 @@
* notify_device_nearby="false"
* revoked="false"
* last_time_connected="1634641160229"
- * time_approved="1634389553216"/>
+ * time_approved="1634389553216"
+ * system_data_sync_flags="-1"/>
*
* <association
* id="3"
@@ -143,7 +144,8 @@
* notify_device_nearby="false"
* revoked="false"
* last_time_connected="1634641160229"
- * time_approved="1634641160229"/>
+ * time_approved="1634641160229"
+ * system_data_sync_flags="-1"/>
* </associations>
*
* <previously-used-ids>
@@ -185,6 +187,7 @@
private static final String XML_ATTR_REVOKED = "revoked";
private static final String XML_ATTR_TIME_APPROVED = "time_approved";
private static final String XML_ATTR_LAST_TIME_CONNECTED = "last_time_connected";
+ private static final String XML_ATTR_SYSTEM_DATA_SYNC_FLAGS = "system_data_sync_flags";
private static final String LEGACY_XML_ATTR_DEVICE = "device";
@@ -429,7 +432,7 @@
out.add(new AssociationInfo(associationId, userId, appPackage,
MacAddress.fromString(deviceAddress), null, profile, null,
/* managedByCompanionApp */ false, notify, /* revoked */ false, timeApproved,
- Long.MAX_VALUE));
+ Long.MAX_VALUE, /* systemDataSyncFlags */ -1));
}
private static void readAssociationsV1(@NonNull TypedXmlPullParser parser,
@@ -462,10 +465,12 @@
final long timeApproved = readLongAttribute(parser, XML_ATTR_TIME_APPROVED, 0L);
final long lastTimeConnected = readLongAttribute(
parser, XML_ATTR_LAST_TIME_CONNECTED, Long.MAX_VALUE);
+ final int systemDataSyncFlags = readIntAttribute(parser,
+ XML_ATTR_SYSTEM_DATA_SYNC_FLAGS, -1);
final AssociationInfo associationInfo = createAssociationInfoNoThrow(associationId, userId,
appPackage, macAddress, displayName, profile, selfManaged, notify, revoked,
- timeApproved, lastTimeConnected);
+ timeApproved, lastTimeConnected, systemDataSyncFlags);
if (associationInfo != null) {
out.add(associationInfo);
}
@@ -523,6 +528,7 @@
writeLongAttribute(serializer, XML_ATTR_TIME_APPROVED, a.getTimeApprovedMs());
writeLongAttribute(
serializer, XML_ATTR_LAST_TIME_CONNECTED, a.getLastTimeConnectedMs());
+ writeIntAttribute(serializer, XML_ATTR_SYSTEM_DATA_SYNC_FLAGS, a.getSystemDataSyncFlags());
serializer.endTag(null, XML_TAG_ASSOCIATION);
}
@@ -561,14 +567,15 @@
private static AssociationInfo createAssociationInfoNoThrow(int associationId,
@UserIdInt int userId, @NonNull String appPackage, @Nullable MacAddress macAddress,
@Nullable CharSequence displayName, @Nullable String profile, boolean selfManaged,
- boolean notify, boolean revoked, long timeApproved, long lastTimeConnected) {
+ boolean notify, boolean revoked, long timeApproved, long lastTimeConnected,
+ int systemDataSyncFlags) {
AssociationInfo associationInfo = null;
try {
// We do not persist AssociatedDevice, which means that AssociationInfo retrieved from
// datastore is not guaranteed to be identical to the one from initial association.
associationInfo = new AssociationInfo(associationId, userId, appPackage, macAddress,
displayName, profile, null, selfManaged, notify, revoked,
- timeApproved, lastTimeConnected);
+ timeApproved, lastTimeConnected, systemDataSyncFlags);
} catch (Exception e) {
if (DEBUG) Log.w(TAG, "Could not create AssociationInfo", e);
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index db163dc..5985ce4 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -34,6 +34,7 @@
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.IVirtualDeviceIntentInterceptor;
+import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
@@ -119,6 +120,7 @@
private final VirtualDeviceParams mParams;
private final Map<Integer, PowerManager.WakeLock> mPerDisplayWakelocks = new ArrayMap<>();
private final IVirtualDeviceActivityListener mActivityListener;
+ private final IVirtualDeviceSoundEffectListener mSoundEffectListener;
@GuardedBy("mVirtualDeviceLock")
private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>();
@NonNull
@@ -170,6 +172,7 @@
OnDeviceCloseListener onDeviceCloseListener,
PendingTrampolineCallback pendingTrampolineCallback,
IVirtualDeviceActivityListener activityListener,
+ IVirtualDeviceSoundEffectListener soundEffectListener,
Consumer<ArraySet<Integer>> runningAppsChangedCallback,
VirtualDeviceParams params) {
this(
@@ -184,6 +187,7 @@
onDeviceCloseListener,
pendingTrampolineCallback,
activityListener,
+ soundEffectListener,
runningAppsChangedCallback,
params);
}
@@ -201,6 +205,7 @@
OnDeviceCloseListener onDeviceCloseListener,
PendingTrampolineCallback pendingTrampolineCallback,
IVirtualDeviceActivityListener activityListener,
+ IVirtualDeviceSoundEffectListener soundEffectListener,
Consumer<ArraySet<Integer>> runningAppsChangedCallback,
VirtualDeviceParams params) {
super(PermissionEnforcer.fromContext(context));
@@ -209,6 +214,7 @@
mAssociationInfo = associationInfo;
mPendingTrampolineCallback = pendingTrampolineCallback;
mActivityListener = activityListener;
+ mSoundEffectListener = soundEffectListener;
mRunningAppsChangedCallback = runningAppsChangedCallback;
mOwnerUid = ownerUid;
mDeviceId = deviceId;
@@ -937,6 +943,14 @@
Toast.LENGTH_LONG, mContext.getMainLooper());
}
+ void playSoundEffect(int effectType) {
+ try {
+ mSoundEffectListener.onPlaySoundEffect(effectType);
+ } catch (RemoteException exception) {
+ Slog.w(TAG, "Unable to invoke sound effect listener", exception);
+ }
+ }
+
/**
* Intercepts intent when matching any of the IntentFilter of any interceptor. Returns true if
* the intent matches any filter notifying the DisplayPolicyController to abort the
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index b0f2464..47ec80e 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -30,6 +30,7 @@
import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.IVirtualDeviceManager;
+import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
@@ -222,7 +223,8 @@
String packageName,
int associationId,
@NonNull VirtualDeviceParams params,
- @NonNull IVirtualDeviceActivityListener activityListener) {
+ @NonNull IVirtualDeviceActivityListener activityListener,
+ @NonNull IVirtualDeviceSoundEffectListener soundEffectListener) {
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"createVirtualDevice");
@@ -246,7 +248,7 @@
VirtualDeviceImpl virtualDevice = new VirtualDeviceImpl(getContext(),
associationInfo, token, callingUid, deviceId, cameraAccessController,
this::onDeviceClosed, mPendingTrampolineCallback, activityListener,
- runningAppsChangedCallback, params);
+ soundEffectListener, runningAppsChangedCallback, params);
mVirtualDevices.put(deviceId, virtualDevice);
return virtualDevice;
}
@@ -364,6 +366,18 @@
}
}
+ @Override // Binder call
+ public void playSoundEffect(int deviceId, int effectType) {
+ VirtualDeviceImpl virtualDevice;
+ synchronized (mVirtualDeviceManagerLock) {
+ virtualDevice = mVirtualDevices.get(deviceId);
+ }
+
+ if (virtualDevice != null) {
+ virtualDevice.playSoundEffect(effectType);
+ }
+ }
+
@Nullable
private AssociationInfo getAssociationInfo(String packageName, int associationId) {
final UserHandle userHandle = getCallingUserHandle();
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f8e79e5..6fb5730 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -44,6 +44,7 @@
import android.util.SparseArray;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.KnownPackages;
import com.android.server.pm.PackageList;
import com.android.server.pm.PackageSetting;
@@ -1320,4 +1321,14 @@
public abstract void setPackageStoppedState(@NonNull String packageName, boolean stopped,
@UserIdInt int userId);
+
+ /** @deprecated For legacy shell command only. */
+ @Deprecated
+ public abstract void legacyDumpProfiles(@NonNull String packageName,
+ boolean dumpClassesAndMethods) throws LegacyDexoptDisabledException;
+
+ /** @deprecated For legacy shell command only. */
+ @Deprecated
+ public abstract void legacyReconcileSecondaryDexFiles(String packageName)
+ throws LegacyDexoptDisabledException;
}
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 661319f3..fce44f5 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -44,6 +44,13 @@
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
+import android.hardware.biometrics.SensorProperties;
+import android.hardware.biometrics.SensorProperties.ComponentInfo;
+import android.hardware.face.FaceManager;
+import android.hardware.face.FaceSensorProperties;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorProperties;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -1067,11 +1074,6 @@
// register a package observer to detect updates to preloads
mPackageManagerInternal.getPackageList(new PackageManagerInternal.PackageListObserver() {
@Override
- public void onPackageAdded(String packageName, int uid) {
-
- }
-
- @Override
public void onPackageChanged(String packageName, int uid) {
// check if the updated package is a preloaded app.
PackageManager pm = mContext.getPackageManager();
@@ -1087,11 +1089,6 @@
UpdateMeasurementsJobService.scheduleBinaryMeasurements(mContext,
BinaryTransparencyService.this);
}
-
- @Override
- public void onPackageRemoved(String packageName, int uid) {
-
- }
});
// TODO(b/264428429): Register observer for updates to APEXs.
@@ -1111,6 +1108,15 @@
Slog.i(TAG, "Boot completed. Getting VBMeta Digest.");
getVBMetaDigestInformation();
+ // Log to statsd
+ // TODO(b/264061957): For now, biometric system properties are always collected if users
+ // share usage & diagnostics information. In the future, collect biometric system
+ // properties only when transparency log verification of the target partitions fails
+ // (e.g. when the system/vendor partitions have been changed) once the binary
+ // transparency infrastructure is ready.
+ Slog.i(TAG, "Boot completed. Collecting biometric system properties.");
+ collectBiometricProperties();
+
// to avoid the risk of holding up boot time, computations to measure APEX, Module, and
// MBA digests are scheduled here, but only executed when the device is idle and plugged
// in.
@@ -1207,6 +1213,141 @@
}
}
+ /**
+ * Convert a {@link FingerprintSensorProperties} sensor type to the corresponding enum to be
+ * logged.
+ *
+ * @param sensorType See {@link FingerprintSensorProperties}
+ * @return The enum to be logged
+ */
+ private int toFingerprintSensorType(@FingerprintSensorProperties.SensorType int sensorType) {
+ switch (sensorType) {
+ case FingerprintSensorProperties.TYPE_REAR:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_REAR;
+ case FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_UDFPS_ULTRASONIC;
+ case FingerprintSensorProperties.TYPE_UDFPS_OPTICAL:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_UDFPS_OPTICAL;
+ case FingerprintSensorProperties.TYPE_POWER_BUTTON:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_POWER_BUTTON;
+ case FingerprintSensorProperties.TYPE_HOME_BUTTON:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FP_HOME_BUTTON;
+ default:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_UNKNOWN;
+ }
+ }
+
+ /**
+ * Convert a {@link FaceSensorProperties} sensor type to the corresponding enum to be logged.
+ *
+ * @param sensorType See {@link FaceSensorProperties}
+ * @return The enum to be logged
+ */
+ private int toFaceSensorType(@FaceSensorProperties.SensorType int sensorType) {
+ switch (sensorType) {
+ case FaceSensorProperties.TYPE_RGB:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FACE_RGB;
+ case FaceSensorProperties.TYPE_IR:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_FACE_IR;
+ default:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_TYPE__SENSOR_UNKNOWN;
+ }
+ }
+
+ /**
+ * Convert a {@link SensorProperties} sensor strength to the corresponding enum to be logged.
+ *
+ * @param sensorStrength See {@link SensorProperties}
+ * @return The enum to be logged
+ */
+ private int toSensorStrength(@SensorProperties.Strength int sensorStrength) {
+ switch (sensorStrength) {
+ case SensorProperties.STRENGTH_CONVENIENCE:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_CONVENIENCE;
+ case SensorProperties.STRENGTH_WEAK:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_WEAK;
+ case SensorProperties.STRENGTH_STRONG:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_STRONG;
+ default:
+ return FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__SENSOR_STRENGTH__STRENGTH_UNKNOWN;
+ }
+ }
+
+ /**
+ * A helper function to log detailed biometric sensor properties to statsd.
+ *
+ * @param prop The biometric sensor properties to be logged
+ * @param modality The modality of the biometric (e.g. fingerprint, face) to be logged
+ * @param sensorType The specific type of the biometric to be logged
+ */
+ private void logBiometricProperties(SensorProperties prop, int modality, int sensorType) {
+ final int sensorId = prop.getSensorId();
+ final int sensorStrength = toSensorStrength(prop.getSensorStrength());
+
+ // Log data for each component
+ // Note: none of the component info is a device identifier since every device of a given
+ // model and build share the same biometric system info (see b/216195167)
+ for (ComponentInfo componentInfo : prop.getComponentInfo()) {
+ FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_PROPERTIES_COLLECTED,
+ sensorId,
+ modality,
+ sensorType,
+ sensorStrength,
+ componentInfo.getComponentId().trim(),
+ componentInfo.getHardwareVersion().trim(),
+ componentInfo.getFirmwareVersion().trim(),
+ componentInfo.getSerialNumber().trim(),
+ componentInfo.getSoftwareVersion().trim());
+ }
+ }
+
+ private void collectBiometricProperties() {
+ PackageManager pm = mContext.getPackageManager();
+ FingerprintManager fpManager = null;
+ FaceManager faceManager = null;
+ if (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+ fpManager = mContext.getSystemService(FingerprintManager.class);
+ }
+ if (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ faceManager = mContext.getSystemService(FaceManager.class);
+ }
+
+ if (fpManager != null) {
+ // Log data for each fingerprint sensor
+ for (FingerprintSensorPropertiesInternal propInternal :
+ fpManager.getSensorPropertiesInternal()) {
+ final FingerprintSensorProperties prop =
+ FingerprintSensorProperties.from(propInternal);
+ logBiometricProperties(prop,
+ FrameworkStatsLog
+ .BIOMETRIC_PROPERTIES_COLLECTED__MODALITY__MODALITY_FINGERPRINT,
+ toFingerprintSensorType(prop.getSensorType()));
+ }
+ }
+
+ if (faceManager != null) {
+ // Log data for each face sensor
+ for (FaceSensorProperties prop : faceManager.getSensorProperties()) {
+ logBiometricProperties(prop,
+ FrameworkStatsLog.BIOMETRIC_PROPERTIES_COLLECTED__MODALITY__MODALITY_FACE,
+ toFaceSensorType(prop.getSensorType()));
+ }
+ }
+ }
+
private void getVBMetaDigestInformation() {
mVbmetaDigest = SystemProperties.get(SYSPROP_NAME_VBETA_DIGEST, VBMETA_DIGEST_UNAVAILABLE);
Slog.d(TAG, String.format("VBMeta Digest: %s", mVbmetaDigest));
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 9bedbd0..7b8ca91 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1000,6 +1000,10 @@
@Override
public void notifySubscriptionInfoChanged() {
if (VDBG) log("notifySubscriptionInfoChanged:");
+ if (!checkNotifyPermission("notifySubscriptionInfoChanged()")) {
+ return;
+ }
+
synchronized (mRecords) {
if (!mHasNotifySubscriptionInfoChangedOccurred) {
log("notifySubscriptionInfoChanged: first invocation mRecords.size="
@@ -1026,6 +1030,10 @@
@Override
public void notifyOpportunisticSubscriptionInfoChanged() {
if (VDBG) log("notifyOpptSubscriptionInfoChanged:");
+ if (!checkNotifyPermission("notifyOpportunisticSubscriptionInfoChanged()")) {
+ return;
+ }
+
synchronized (mRecords) {
if (!mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
log("notifyOpptSubscriptionInfoChanged: first invocation mRecords.size="
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index ae50b23..2b43ef4 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -67,6 +68,7 @@
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.VpnProfileStore;
import com.android.server.net.LockdownVpnTracker;
+import com.android.server.pm.UserManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -93,6 +95,7 @@
private final INetworkManagementService mNMS;
private final INetd mNetd;
private final UserManager mUserManager;
+ private final int mMainUserId;
@VisibleForTesting
@GuardedBy("mVpns")
@@ -145,6 +148,12 @@
Vpn vpn, VpnProfile profile) {
return new LockdownVpnTracker(context, handler, vpn, profile);
}
+
+ /** Get the main user on the device. */
+ public @UserIdInt int getMainUserId() {
+ // TODO(b/265785220): Change to use UserManager method instead.
+ return LocalServices.getService(UserManagerInternal.class).getMainUserId();
+ }
}
public VpnManagerService(Context context, Dependencies deps) {
@@ -159,6 +168,7 @@
mNMS = mDeps.getINetworkManagementService();
mNetd = mDeps.getNetd();
mUserManager = mContext.getSystemService(UserManager.class);
+ mMainUserId = mDeps.getMainUserId();
registerReceivers();
log("VpnManagerService starting up");
}
@@ -478,11 +488,12 @@
@Override
public boolean updateLockdownVpn() {
- // Allow the system UID for the system server and for Settings.
+ // Allow the system UID for the system server and for Settings (from user 0 or main user).
// Also, for unit tests, allow the process that ConnectivityService is running in.
if (mDeps.getCallingUid() != Process.SYSTEM_UID
+ && mDeps.getCallingUid() != UserHandle.getUid(mMainUserId, Process.SYSTEM_UID)
&& Binder.getCallingPid() != Process.myPid()) {
- logw("Lockdown VPN only available to system process or AID_SYSTEM");
+ logw("Lockdown VPN only available to system process or AID_SYSTEM on main user");
return false;
}
@@ -697,7 +708,7 @@
intentFilter,
null /* broadcastPermission */,
mHandler);
- mContext.createContextAsUser(UserHandle.SYSTEM, 0 /* flags */).registerReceiver(
+ mContext.createContextAsUser(UserHandle.of(mMainUserId), 0 /* flags */).registerReceiver(
mUserPresentReceiver,
new IntentFilter(Intent.ACTION_USER_PRESENT),
null /* broadcastPermission */,
@@ -735,6 +746,7 @@
if (LockdownVpnTracker.ACTION_LOCKDOWN_RESET.equals(action)) {
onVpnLockdownReset();
+ return;
}
// UserId should be filled for below intents, check the existence.
@@ -795,7 +807,7 @@
userVpn = mDeps.createVpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId);
mVpns.put(userId, userVpn);
- if (user.isPrimary() && isLockdownVpnEnabled()) {
+ if (userId == mMainUserId && isLockdownVpnEnabled()) {
updateLockdownVpn();
}
}
@@ -910,15 +922,9 @@
}
private void onUserUnlocked(int userId) {
- UserInfo user = mUserManager.getUserInfo(userId);
- if (user == null) {
- logw("Unlocked user doesn't exist. UserId: " + userId);
- return;
- }
-
synchronized (mVpns) {
// User present may be sent because of an unlock, which might mean an unlocked keystore.
- if (user.isPrimary() && isLockdownVpnEnabled()) {
+ if (userId == mMainUserId && isLockdownVpnEnabled()) {
updateLockdownVpn();
} else {
startAlwaysOnVpn(userId);
@@ -984,7 +990,7 @@
}
// Turn Always-on VPN off
- if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
+ if (mLockdownEnabled && userId == mMainUserId) {
final long ident = Binder.clearCallingIdentity();
try {
mVpnProfileStore.remove(Credentials.LOCKDOWN_VPN);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 35b5f1b..c16314b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1491,13 +1491,7 @@
Account[] sharedAccounts = getSharedAccountsAsUser(userId);
if (sharedAccounts == null || sharedAccounts.length == 0) return;
Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName());
- int parentUserId = UserManager.isSplitSystemUser()
- ? getUserManager().getUserInfo(userId).restrictedProfileParentId
- : UserHandle.USER_SYSTEM;
- if (parentUserId < 0) {
- Log.w(TAG, "User " + userId + " has shared accounts, but no parent user");
- return;
- }
+ int parentUserId = UserHandle.USER_SYSTEM;
for (Account sa : sharedAccounts) {
if (ArrayUtils.contains(accounts, sa)) continue;
// Account doesn't exist. Copy it now.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6719fdb..41437d1 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1940,6 +1940,12 @@
ignoreForeground = true;
}
+ // Whether FGS-BG-start restriction is enabled for this service.
+ final boolean isBgFgsRestrictionEnabledForService = isBgFgsRestrictionEnabled(r);
+
+ // Whether to extend the SHORT_SERVICE time out.
+ boolean extendShortServiceTimeout = false;
+
int fgsTypeCheckCode = FGS_TYPE_POLICY_CHECK_UNKNOWN;
if (!ignoreForeground) {
if (foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE
@@ -1955,41 +1961,77 @@
"startForeground(SHORT_SERVICE) called on a service that's not"
+ " started.");
}
- // If the service is already an FGS, and the type is changing, then we
- // may need to do some extra work here.
- if (r.isForeground && (r.foregroundServiceType != foregroundServiceType)) {
- // TODO(short-service): Consider transitions:
- // A. Short -> other types:
- // Apply the BG restriction again. Don't just allow it.
- // i.e. unless the app is in a situation where it's allowed to start
- // a FGS, this transition shouldn't be allowed.
- // ... But think about it more, there may be a case this should be
- // allowed.
- //
- // If the transition is allowed, stop the timeout.
- // If the transition is _not_ allowed... keep the timeout?
- //
- // B. Short -> Short:
- // Allowed, but the timeout won't reset. The original timeout is used.
- // C. Other -> short:
- // This should always be allowed.
- // A timeout should start.
- // For now, let's just disallow transition from / to SHORT_SERVICE.
- final boolean isNewTypeShortFgs =
- foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
- if (r.isShortFgs() != isNewTypeShortFgs) {
- // TODO(short-service): We should (probably) allow it.
- throw new IllegalArgumentException(
- "setForeground(): Changing foreground service type from / to "
- + " SHORT_SERVICE is now allowed");
+ // Side note: If a valid short-service (which has to be "started"), happens to
+ // also be bound, then we still _will_ apply a timeout, because it still has
+ // to be stopped.
+
+ // Calling startForeground on a SHORT_SERVICE will require some additional
+ // checks.
+ // A) SHORT_SERVICE -> another type.
+ // - This should be allowed only when the app could start another FGS.
+ // - When succeed, the timeout should stop.
+ // B) SHORT_SERVICE -> SHORT_SERVICE
+ // - If the app could start an FGS, then this would extend the timeout.
+ // - Otherwise, it's basically a no-op.
+ // - If it's already timed out, we also throw.
+ // Also,
+ // C) another type -> SHORT_SERVICE
+ // - This will always be allowed.
+ // - Timeout will start.
+
+ final boolean isOldTypeShortFgs = r.isShortFgs();
+ final boolean isNewTypeShortFgs =
+ foregroundServiceType == FOREGROUND_SERVICE_TYPE_SHORT_SERVICE;
+ final boolean isOldTypeShortFgsAndTimedOut = r.shouldTriggerShortFgsTimeout();
+
+ if (isOldTypeShortFgs || isNewTypeShortFgs) {
+ if (DEBUG_SHORT_SERVICE) {
+ Slog.i(TAG_SERVICE, String.format(
+ "FGS type changing from %x%s to %x: %s",
+ r.foregroundServiceType,
+ (isOldTypeShortFgsAndTimedOut ? "(timed out short FGS)" : ""),
+ foregroundServiceStartType,
+ r.toString()));
}
}
- // If a valid short-service (which has to be "started"), happens to
- // also be bound, then we still _will_ apply a timeout, because it still has
- // to be stopped.
- if (r.mStartForegroundCount == 0) {
+ if (r.isForeground && isOldTypeShortFgs) {
+ // If we get here, that means startForeground(SHORT_SERVICE) is called again
+ // on a SHORT_SERVICE FGS.
+
+ // See if the app could start an FGS or not.
+ r.mAllowStartForeground = REASON_DENIED;
+ setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.getPid(),
+ r.appInfo.uid, r.intent.getIntent(), r, r.userId,
+ BackgroundStartPrivileges.NONE,
+ false /* isBindService */);
+
+ final boolean fgsStartAllowed =
+ !isBgFgsRestrictionEnabledForService
+ || (r.mAllowStartForeground != REASON_DENIED);
+
+ if (fgsStartAllowed) {
+ if (isNewTypeShortFgs) {
+ // Only in this case, we extend the SHORT_SERVICE time out.
+ extendShortServiceTimeout = true;
+ if (DEBUG_SHORT_SERVICE) {
+ Slog.i(TAG_SERVICE, "Extending SHORT_SERVICE time out: " + r);
+ }
+ } else {
+ // FGS type is changing from SHORT_SERVICE to another type when
+ // an app is allowed to start FGS, so this will succeed.
+ // The timeout will stop -- we actually don't cancel the handler
+ // events, but they'll be ignored if the service type is not
+ // SHORT_SERVICE.
+ // TODO(short-service) Let's actaully cancel the handler events.
+ }
+ } else {
+ // We catch this case later, in the
+ // "if (r.mAllowStartForeground == REASON_DENIED...)" block below.
+ }
+
+ } else if (r.mStartForegroundCount == 0) {
/*
If the service was started with startService(), not
startForegroundService(), and if startForeground() isn't called within
@@ -2032,6 +2074,7 @@
BackgroundStartPrivileges.NONE,
false /* isBindService */);
}
+
// If the foreground service is not started from TOP process, do not allow it to
// have while-in-use location/camera/microphone access.
if (!r.mAllowWhileInUsePermissionInFgs) {
@@ -2041,10 +2084,12 @@
+ r.shortInstanceName);
}
logFgsBackgroundStart(r);
- if (r.mAllowStartForeground == REASON_DENIED && isBgFgsRestrictionEnabled(r)) {
+ if (r.mAllowStartForeground == REASON_DENIED
+ && isBgFgsRestrictionEnabledForService) {
final String msg = "Service.startForeground() not allowed due to "
+ "mAllowStartForeground false: service "
- + r.shortInstanceName;
+ + r.shortInstanceName
+ + (isOldTypeShortFgs ? " (Called on SHORT_SERVICE)" : "");
Slog.w(TAG, msg);
showFgsBgRestrictedNotificationLocked(r);
updateServiceForegroundLocked(psr, true);
@@ -2181,11 +2226,8 @@
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
- // Note, we'll get here if setForeground(SHORT_SERVICE) is called on a
- // already short-fgs.
- // In that case, because ShortFgsInfo is already set, this method
- // will be noop.
- maybeStartShortFgsTimeoutAndUpdateShortFgsInfoLocked(r);
+ maybeStartShortFgsTimeoutAndUpdateShortFgsInfoLocked(r,
+ extendShortServiceTimeout);
} else {
if (DEBUG_FOREGROUND_SERVICE) {
Slog.d(TAG, "Suppressing startForeground() for FAS " + r);
@@ -2982,17 +3024,21 @@
/**
* If {@code sr} is of a short-fgs, start a short-FGS timeout.
*/
- private void maybeStartShortFgsTimeoutAndUpdateShortFgsInfoLocked(ServiceRecord sr) {
+ private void maybeStartShortFgsTimeoutAndUpdateShortFgsInfoLocked(ServiceRecord sr,
+ boolean extendTimeout) {
if (!sr.isShortFgs()) {
return;
}
if (DEBUG_SHORT_SERVICE) {
Slog.i(TAG_SERVICE, "Short FGS started: " + sr);
}
- if (sr.hasShortFgsInfo()) {
- sr.getShortFgsInfo().update();
- } else {
+
+ if (extendTimeout || !sr.hasShortFgsInfo()) {
sr.setShortFgsInfo(SystemClock.uptimeMillis());
+ } else {
+ // We only (potentially) update the start command, start count, but not the timeout
+ // time.
+ sr.getShortFgsInfo().update();
}
unscheduleShortFgsTimeoutLocked(sr); // Do it just in case
@@ -7562,7 +7608,8 @@
if (!r.mLoggedInfoAllowStartForeground) {
final String msg = "Background started FGS: "
+ ((r.mAllowStartForeground != REASON_DENIED) ? "Allowed " : "Disallowed ")
- + r.mInfoAllowStartForeground;
+ + r.mInfoAllowStartForeground
+ + (r.isShortFgs() ? " (Called on SHORT_SERVICE)" : "");
if (r.mAllowStartForeground != REASON_DENIED) {
if (ActivityManagerUtils.shouldSamplePackageForAtom(r.packageName,
mAm.mConstants.mFgsStartAllowedLogSampleRate)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerLocal.java b/services/core/java/com/android/server/am/ActivityManagerLocal.java
index abaa8c7..31ea092 100644
--- a/services/core/java/com/android/server/am/ActivityManagerLocal.java
+++ b/services/core/java/com/android/server/am/ActivityManagerLocal.java
@@ -75,8 +75,9 @@
* @param conn Receives information as the service is started and stopped.
* This must be a valid ServiceConnection object; it must not be null.
* @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned.
- * @param clientApplicationThread ApplicationThread object of the app for which the sdk sandboox
- * is spawned.
+ * @param clientAppProcessToken process token used to uniquely identify the client app
+ * process binding to the SDK sandbox. This is obtained using
+ * {@link Context#getProcessToken()}.
* @param clientAppPackage Package of the app for which the sdk sandbox process needs to
* be spawned. This package must belong to the clientAppUid.
* @param processName Unique identifier for the service instance. Each unique name here will
@@ -92,7 +93,7 @@
*/
@SuppressLint("RethrowRemoteException")
boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
- int clientAppUid, @NonNull IBinder clientApplicationThread,
+ int clientAppUid, @NonNull IBinder clientAppProcessToken,
@NonNull String clientAppPackage, @NonNull String processName,
@Context.BindServiceFlags int flags)
throws RemoteException;
@@ -112,9 +113,9 @@
/**
* Kill an app process associated with an SDK sandbox.
*
- * @param clientApplicationThreadBinder binder value of the
- * {@link android.app.IApplicationThread} of a client app process associated with a
- * sandbox. This is obtained using {@link Context#getIApplicationThreadBinder()}.
+ * @param clientAppProcessToken process token used to uniquely identify the client app
+ * process associated with an SDK sandbox. This is obtained using
+ * {@link Context#getProcessToken()}.
*/
- void killSdkSandboxClientAppProcess(@NonNull IBinder clientApplicationThreadBinder);
+ void killSdkSandboxClientAppProcess(@NonNull IBinder clientAppProcessToken);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8e1f969..de87a0c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1606,8 +1606,6 @@
// Encapsulates the global setting "hidden_api_blacklist_exemptions"
final HiddenApiSettings mHiddenApiBlacklist;
- final SdkSandboxSettings mSdkSandboxSettings;
-
private final PlatformCompat mPlatformCompat;
PackageManagerInternal mPackageManagerInt;
@@ -2324,53 +2322,6 @@
}
}
- /**
- * Handles settings related to the enforcement of SDK sandbox restrictions.
- */
- static class SdkSandboxSettings implements DeviceConfig.OnPropertiesChangedListener {
-
- private final Context mContext;
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private boolean mEnforceBroadcastReceiverRestrictions;
-
- /**
- * Property to enforce broadcast receiver restrictions for SDK sandbox processes. If the
- * value of this property is {@code true}, the restrictions will be enforced.
- */
- public static final String ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS =
- "enforce_broadcast_receiver_restrictions";
-
- SdkSandboxSettings(Context context) {
- mContext = context;
- }
-
- void registerObserver() {
- synchronized (mLock) {
- mEnforceBroadcastReceiverRestrictions = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SDK_SANDBOX,
- ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS, false);
- DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SDK_SANDBOX,
- mContext.getMainExecutor(), this);
- }
- }
-
- @Override
- public void onPropertiesChanged(DeviceConfig.Properties properties) {
- synchronized (mLock) {
- mEnforceBroadcastReceiverRestrictions = properties.getBoolean(
- ENFORCE_BROADCAST_RECEIVER_RESTRICTIONS, false);
- }
- }
-
- boolean isBroadcastReceiverRestrictionsEnforced() {
- synchronized (mLock) {
- return mEnforceBroadcastReceiverRestrictions;
- }
- }
- }
-
AppOpsManager getAppOpsManager() {
if (mAppOpsManager == null) {
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
@@ -2414,7 +2365,6 @@
mProcStartHandlerThread = null;
mProcStartHandler = null;
mHiddenApiBlacklist = null;
- mSdkSandboxSettings = null;
mFactoryTest = FACTORY_TEST_OFF;
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
mInternal = new LocalService();
@@ -2539,7 +2489,6 @@
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
- mSdkSandboxSettings = new SdkSandboxSettings(mContext);
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
@@ -6694,6 +6643,10 @@
@Override
public void appNotResponding(final String reason) {
+ appNotResponding(reason, /*isContinuousAnr*/ false);
+ }
+
+ public void appNotResponding(final String reason, boolean isContinuousAnr) {
TimeoutRecord timeoutRecord = TimeoutRecord.forApp("App requested: " + reason);
final int callingPid = Binder.getCallingPid();
@@ -6706,7 +6659,7 @@
}
mAnrHelper.appNotResponding(app, null, app.info, null, null, false,
- timeoutRecord);
+ timeoutRecord, isContinuousAnr);
}
}
@@ -7434,11 +7387,12 @@
if (shareDescription != null) {
triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
}
- UserHandle callingUser = Binder.getCallingUserHandle();
final long identity = Binder.clearCallingIdentity();
try {
// Send broadcast to shell to trigger bugreport using Bugreport API
- mContext.sendBroadcastAsUser(triggerShellBugreport, callingUser);
+ // Always start the shell process on the current user to ensure that
+ // the foreground user can see all bugreport notifications.
+ mContext.sendBroadcastAsUser(triggerShellBugreport, getCurrentUser().getUserHandle());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -7510,7 +7464,10 @@
*/
@Override
public boolean launchBugReportHandlerApp() {
- if (!BugReportHandlerUtil.isBugReportHandlerEnabled(mContext)) {
+
+ Context currentUserContext = mContext.createContextAsUser(getCurrentUser().getUserHandle(),
+ /* flags= */ 0);
+ if (!BugReportHandlerUtil.isBugReportHandlerEnabled(currentUserContext)) {
return false;
}
@@ -7519,7 +7476,7 @@
enforceCallingPermission(android.Manifest.permission.DUMP,
"launchBugReportHandlerApp");
- return BugReportHandlerUtil.launchBugReportHandlerApp(mContext);
+ return BugReportHandlerUtil.launchBugReportHandlerApp(currentUserContext);
}
/**
@@ -8292,7 +8249,6 @@
final boolean alwaysFinishActivities =
Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
mHiddenApiBlacklist.registerObserver();
- mSdkSandboxSettings.registerObserver();
mPlatformCompat.registerContentObserver();
mAppProfiler.retrieveSettings();
@@ -8463,10 +8419,7 @@
// Enable home activity for system user, so that the system can always boot. We don't
// do this when the system user is not setup since the setup wizard should be the one
// to handle home activity in this case.
- if (UserManager.isSplitSystemUser() &&
- Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0, currentUserId) != 0
- || SystemProperties.getBoolean(SYSTEM_USER_HOME_NEEDED, false)) {
+ if (SystemProperties.getBoolean(SYSTEM_USER_HOME_NEEDED, false)) {
t.traceBegin("enableHomeActivity");
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
@@ -13537,16 +13490,6 @@
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
enforceNotIsolatedCaller("registerReceiver");
-
- // Allow Sandbox process to register only unexported receivers.
- boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
- if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
- && Process.isSdkSandboxUid(Binder.getCallingUid())
- && !unexported) {
- throw new SecurityException("SDK sandbox process not allowed to call "
- + "registerReceiver");
- }
-
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
@@ -13610,6 +13553,20 @@
}
}
+ if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
+ SdkSandboxManagerLocal sdkSandboxManagerLocal =
+ LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
+ if (sdkSandboxManagerLocal == null) {
+ throw new IllegalStateException("SdkSandboxManagerLocal not found when checking"
+ + " whether SDK sandbox uid can register to broadcast receivers.");
+ }
+ if (!sdkSandboxManagerLocal.canRegisterBroadcastReceiver(
+ /*IntentFilter=*/ filter, flags, onlyProtectedBroadcasts)) {
+ throw new SecurityException("SDK sandbox not allowed to register receiver"
+ + " with the given IntentFilter");
+ }
+ }
+
// If the change is enabled, but neither exported or not exported is set, we need to log
// an error so the consumer can know to explicitly set the value for their flag.
// If the caller is registering for a sticky broadcast with a null receiver, we won't
@@ -18401,7 +18358,8 @@
}
}
mAnrHelper.appNotResponding(proc, activityShortComponentName, aInfo,
- parentShortComponentName, parentProcess, aboveSystem, timeoutRecord);
+ parentShortComponentName, parentProcess, aboveSystem, timeoutRecord,
+ /*isContinuousAnr*/ true);
}
return true;
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index 71c80ea..463a2f8 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -96,13 +96,13 @@
void appNotResponding(ProcessRecord anrProcess, TimeoutRecord timeoutRecord) {
appNotResponding(anrProcess, null /* activityShortComponentName */, null /* aInfo */,
null /* parentShortComponentName */, null /* parentProcess */,
- false /* aboveSystem */, timeoutRecord);
+ false /* aboveSystem */, timeoutRecord, /*isContinuousAnr*/ false);
}
void appNotResponding(ProcessRecord anrProcess, String activityShortComponentName,
ApplicationInfo aInfo, String parentShortComponentName,
WindowProcessController parentProcess, boolean aboveSystem,
- TimeoutRecord timeoutRecord) {
+ TimeoutRecord timeoutRecord, boolean isContinuousAnr) {
try {
timeoutRecord.mLatencyTracker.appNotRespondingStarted();
final int incomingPid = anrProcess.mPid;
@@ -132,7 +132,7 @@
timeoutRecord.mLatencyTracker.anrRecordPlacingOnQueueWithSize(mAnrRecords.size());
mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
parentShortComponentName, parentProcess, aboveSystem,
- mAuxiliaryTaskExecutor, timeoutRecord));
+ mAuxiliaryTaskExecutor, timeoutRecord, isContinuousAnr));
}
startAnrConsumerIfNeeded();
} finally {
@@ -230,10 +230,12 @@
final boolean mAboveSystem;
final ExecutorService mAuxiliaryTaskExecutor;
final long mTimestamp = SystemClock.uptimeMillis();
+ final boolean mIsContinuousAnr;
AnrRecord(ProcessRecord anrProcess, String activityShortComponentName,
ApplicationInfo aInfo, String parentShortComponentName,
WindowProcessController parentProcess, boolean aboveSystem,
- ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord) {
+ ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord,
+ boolean isContinuousAnr) {
mApp = anrProcess;
mPid = anrProcess.mPid;
mActivityShortComponentName = activityShortComponentName;
@@ -243,6 +245,7 @@
mParentProcess = parentProcess;
mAboveSystem = aboveSystem;
mAuxiliaryTaskExecutor = auxiliaryTaskExecutor;
+ mIsContinuousAnr = isContinuousAnr;
}
void appNotResponding(boolean onlyDumpSelf) {
@@ -250,7 +253,8 @@
mTimeoutRecord.mLatencyTracker.anrProcessingStarted();
mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo,
mParentShortComponentName, mParentProcess, mAboveSystem,
- mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf);
+ mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf,
+ mIsContinuousAnr);
} finally {
mTimeoutRecord.mLatencyTracker.anrProcessingEnded();
}
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 5fe8427..d3e91da 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -169,8 +169,10 @@
errState.getDialogController().clearAnrDialogs();
}
mService.mServices.scheduleServiceTimeoutLocked(app);
- // If the app remains unresponsive, show the dialog again after a delay.
- mService.mInternal.rescheduleAnrDialog(mData);
+ if (mData.isContinuousAnr) {
+ // If the app remains unresponsive, show the dialog again after a delay.
+ mService.mInternal.rescheduleAnrDialog(mData);
+ }
}
break;
}
@@ -197,10 +199,17 @@
final ApplicationInfo aInfo;
final boolean aboveSystem;
- Data(ProcessRecord proc, ApplicationInfo aInfo, boolean aboveSystem) {
+ // If true, then even if the user presses "WAIT" on the ANR dialog,
+ // we'll show it again until the app start responding again.
+ // (we only use it for input dispatch ANRs)
+ final boolean isContinuousAnr;
+
+ Data(ProcessRecord proc, ApplicationInfo aInfo, boolean aboveSystem,
+ boolean isContinuousAnr) {
this.proc = proc;
this.aInfo = aInfo;
this.aboveSystem = aboveSystem;
+ this.isContinuousAnr = isContinuousAnr;
}
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 5b453b2..0327d16 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -380,7 +380,7 @@
}
mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats,
mBatteryUsageStatsStore);
- mCpuWakeupStats = new CpuWakeupStats(context, R.xml.irq_device_map);
+ mCpuWakeupStats = new CpuWakeupStats(context, R.xml.irq_device_map, mHandler);
}
public void publish() {
diff --git a/services/core/java/com/android/server/am/BugReportHandlerUtil.java b/services/core/java/com/android/server/am/BugReportHandlerUtil.java
index 2142ebc..63b14b8 100644
--- a/services/core/java/com/android/server/am/BugReportHandlerUtil.java
+++ b/services/core/java/com/android/server/am/BugReportHandlerUtil.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.AppOpsManager.OP_NONE;
+
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -66,29 +67,29 @@
* Launches a bugreport-allowlisted app to handle a bugreport.
*
* <p>Allows a bug report handler app to take bugreports on the user's behalf. The handler can
- * be predefined in the config, meant to be launched with the primary user. The user can
- * override this with a different (or same) handler app on possibly a different user. This is
- * useful for capturing bug reports from work profile, for instance.
- *
- * @param context Context
- * @return true if there is a bugreport-allowlisted app to handle a bugreport, or false
+ * be predefined in the config, meant to be launched with the current foreground user. The user
+ * can override this with a different (or same) handler app on possibly a different
+ * user profile. This is useful for capturing bug reports from work profile, for instance.
+ * @param userContext Context of the current foreground user
+ * @return true if there is a bugreport-allow-listed app to handle a bugreport, or false
* otherwise
*/
- static boolean launchBugReportHandlerApp(Context context) {
- if (!isBugReportHandlerEnabled(context)) {
+ static boolean launchBugReportHandlerApp(Context userContext) {
+ if (!isBugReportHandlerEnabled(userContext)) {
return false;
}
- String handlerApp = getCustomBugReportHandlerApp(context);
+ String handlerApp = getCustomBugReportHandlerApp(userContext);
if (isShellApp(handlerApp)) {
return false;
}
- int handlerUser = getCustomBugReportHandlerUser(context);
+ int handlerUser = getCustomBugReportHandlerUser(userContext);
if (!isValidBugReportHandlerApp(handlerApp)) {
- handlerApp = getDefaultBugReportHandlerApp(context);
- handlerUser = UserHandle.USER_SYSTEM;
- } else if (getBugReportHandlerAppReceivers(context, handlerApp, handlerUser).isEmpty()) {
+ handlerApp = getDefaultBugReportHandlerApp(userContext);
+ handlerUser = userContext.getUserId();
+ } else if (getBugReportHandlerAppReceivers(userContext, handlerApp, handlerUser)
+ .isEmpty()) {
// It looks like the settings are outdated, reset outdated settings.
//
// i.e.
@@ -97,21 +98,23 @@
// === RESULT ===
// The chosen bugreport handler app is outdated because the profile is removed,
// so reset the chosen app and profile
- handlerApp = getDefaultBugReportHandlerApp(context);
- handlerUser = UserHandle.USER_SYSTEM;
- resetCustomBugreportHandlerAppAndUser(context);
+ handlerApp = getDefaultBugReportHandlerApp(userContext);
+ handlerUser = userContext.getUserId();
+ resetCustomBugreportHandlerAppAndUser(userContext);
}
if (isShellApp(handlerApp) || !isValidBugReportHandlerApp(handlerApp)
- || getBugReportHandlerAppReceivers(context, handlerApp, handlerUser).isEmpty()) {
+ || getBugReportHandlerAppReceivers(userContext, handlerApp, handlerUser)
+ .isEmpty()) {
return false;
}
- if (getBugReportHandlerAppResponseReceivers(context, handlerApp, handlerUser).isEmpty()) {
+ if (getBugReportHandlerAppResponseReceivers(userContext, handlerApp, handlerUser)
+ .isEmpty()) {
// Just try to launch bugreport handler app to handle bugreport request
// because the bugreport handler app is old and not support to provide response to
// let BugReportHandlerUtil know it is available or not.
- launchBugReportHandlerApp(context, handlerApp, handlerUser);
+ launchBugReportHandlerApp(userContext, handlerApp, handlerUser);
return true;
}
@@ -124,7 +127,7 @@
try {
// Handler app's BroadcastReceiver should call setResultCode(Activity.RESULT_OK) to
// let BugreportHandlerResponseBroadcastReceiver know the handler app is available.
- context.sendOrderedBroadcastAsUser(intent,
+ userContext.sendOrderedBroadcastAsUser(intent,
UserHandle.of(handlerUser),
android.Manifest.permission.DUMP,
OP_NONE, /* options= */ null,
@@ -166,13 +169,14 @@
private static String getCustomBugReportHandlerApp(Context context) {
// Get the package of custom bugreport handler app
- return Settings.Global.getString(context.getContentResolver(),
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_APP);
+ return Settings.Secure.getStringForUser(context.getContentResolver(),
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_APP, context.getUserId());
}
private static int getCustomBugReportHandlerUser(Context context) {
- return Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER, UserHandle.USER_NULL);
+ return Settings.Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER, UserHandle.USER_NULL,
+ context.getUserId());
}
private static boolean isShellApp(String app) {
@@ -219,11 +223,11 @@
private static void resetCustomBugreportHandlerAppAndUser(Context context) {
final long identity = Binder.clearCallingIdentity();
try {
- Settings.Global.putString(context.getContentResolver(),
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_APP,
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_APP,
getDefaultBugReportHandlerApp(context));
- Settings.Global.putInt(context.getContentResolver(),
- Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER, UserHandle.USER_SYSTEM);
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.CUSTOM_BUGREPORT_HANDLER_USER, context.getUserId());
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index d2fb7b5..85de637 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -83,11 +83,13 @@
import com.android.internal.os.TimeoutRecord;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.RescueParty;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.sdksandbox.SdkSandboxManagerLocal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -124,13 +126,6 @@
ContentProviderHolder getContentProvider(IApplicationThread caller, String callingPackage,
String name, int userId, boolean stable) {
mService.enforceNotIsolatedCaller("getContentProvider");
- if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
- // TODO(b/226318628): for sdk sandbox processes only allow accessing CPs registered by
- // the WebView apk.
- Slog.w(TAG, "Sdk sandbox process " + Binder.getCallingUid()
- + " is accessing content provider " + name
- + ". This access will most likely be blocked in the future");
- }
if (caller == null) {
String msg = "null IApplicationThread when getting content provider " + name;
Slog.w(TAG, msg);
@@ -255,6 +250,7 @@
if (r != null && cpr.canRunHere(r)) {
checkAssociationAndPermissionLocked(r, cpi, callingUid, userId, checkCrossUser,
cpr.name.flattenToShortString(), startTime);
+ enforceContentProviderRestrictionsForSdkSandbox(cpi);
// This provider has been published or is in the process
// of being published... but it is also allowed to run
@@ -447,6 +443,7 @@
// info and allow the caller to instantiate it. Only do
// this if the provider is the same user as the caller's
// process, or can run as root (so can be in any process).
+ enforceContentProviderRestrictionsForSdkSandbox(cpi);
return cpr.newHolder(null, true);
}
@@ -589,6 +586,8 @@
// Return a holder instance even if we are waiting for the publishing of the
// provider, client will check for the holder.provider to see if it needs to wait
// for it.
+ //todo(b/265965249) Need to perform cleanup before calling enforce method here
+ enforceContentProviderRestrictionsForSdkSandbox(cpi);
return cpr.newHolder(conn, false);
}
}
@@ -650,6 +649,7 @@
+ " caller=" + callerName + "/" + Binder.getCallingUid());
return null;
}
+ enforceContentProviderRestrictionsForSdkSandbox(cpi);
return cpr.newHolder(conn, false);
}
@@ -1230,6 +1230,7 @@
appName = r.toString();
}
+ enforceContentProviderRestrictionsForSdkSandbox(cpi);
return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(),
userId, checkUser, appName);
}
@@ -1998,6 +1999,26 @@
}
}
+ // Binder.clearCallingIdentity() shouldn't be called before this method
+ // as Binder should have its original callingUid for the check
+ private void enforceContentProviderRestrictionsForSdkSandbox(ProviderInfo cpi) {
+ if (!Process.isSdkSandboxUid(Binder.getCallingUid())) {
+ return;
+ }
+ final SdkSandboxManagerLocal sdkSandboxManagerLocal =
+ LocalManagerRegistry.getManager(SdkSandboxManagerLocal.class);
+ if (sdkSandboxManagerLocal == null) {
+ throw new IllegalStateException("SdkSandboxManagerLocal not found "
+ + "when checking whether SDK sandbox uid may "
+ + "access the contentprovider.");
+ }
+ if (!sdkSandboxManagerLocal
+ .canAccessContentProviderFromSdkSandbox(cpi)) {
+ throw new SecurityException(
+ "SDK sandbox uid may not access contentprovider " + cpi.name);
+ }
+ }
+
/**
* There are three ways to call this:
* - no provider specified: dump all the providers
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 874fda3..43075bc 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -22,16 +22,21 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.BackgroundStartPrivileges;
import android.app.BroadcastOptions;
import android.app.IApplicationThread;
import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerWhitelistManager;
@@ -40,6 +45,7 @@
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -56,6 +62,13 @@
public final class PendingIntentRecord extends IIntentSender.Stub {
private static final String TAG = TAG_WITH_CLASS_NAME ? "PendingIntentRecord" : TAG_AM;
+ /** If enabled BAL are prevented by default in applications targeting U and later. */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ private static final long DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER = 244637991;
+ private static final String ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER =
+ "enable_default_rescind_bal_privileges_from_pending_intent_sender";
+
public static final int FLAG_ACTIVITY_SENDER = 1 << 0;
public static final int FLAG_BROADCAST_SENDER = 1 << 1;
public static final int FLAG_SERVICE_SENDER = 1 << 2;
@@ -357,16 +370,34 @@
: BackgroundStartPrivileges.NONE;
}
+ private static boolean isDefaultRescindBalPrivilegesFromPendingIntentSenderEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER,
+ false); // assume false if the property is unknown
+ }
+
/**
* Default {@link BackgroundStartPrivileges} to be used if the intent sender has not made an
* explicit choice.
*
* @hide
*/
- public static BackgroundStartPrivileges getDefaultBackgroundStartPrivileges(int callingUid) {
- // TODO: In the next step this will return ALLOW_FGS instead, if the app that sent the
- // PendingIntent is targeting Android U
- return BackgroundStartPrivileges.ALLOW_BAL;
+ @RequiresPermission(
+ allOf = {
+ android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+ android.Manifest.permission.LOG_COMPAT_CHANGE
+ })
+ public static BackgroundStartPrivileges getDefaultBackgroundStartPrivileges(
+ int callingUid) {
+ boolean isFlagEnabled = isDefaultRescindBalPrivilegesFromPendingIntentSenderEnabled();
+ boolean isChangeEnabledForApp = CompatChanges.isChangeEnabled(
+ DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER, callingUid);
+ if (isFlagEnabled && isChangeEnabledForApp) {
+ return BackgroundStartPrivileges.ALLOW_FGS;
+ } else {
+ return BackgroundStartPrivileges.ALLOW_BAL;
+ }
}
@Deprecated
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 68d906b..9bb63d3 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -263,7 +263,8 @@
void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
String parentShortComponentName, WindowProcessController parentProcess,
boolean aboveSystem, TimeoutRecord timeoutRecord,
- ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf) {
+ ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf,
+ boolean isContinuousAnr) {
String annotation = timeoutRecord.mReason;
AnrLatencyTracker latencyTracker = timeoutRecord.mLatencyTracker;
Future<?> updateCpuStatsNowFirstCall = null;
@@ -630,7 +631,8 @@
// Bring up the infamous App Not Responding dialog
Message msg = Message.obtain();
msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
- msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem);
+ msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem,
+ isContinuousAnr);
mService.mUiHandler.sendMessageDelayed(msg, anrDialogDelayMs);
}
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index 4e1d1ca..c6a8bcd 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -90,7 +90,7 @@
]
},
{
- "file_patterns": ["Broadcast"],
+ "file_patterns": ["Broadcast.*"],
"name": "FrameworksMockingServicesTests",
"options": [
{ "include-filter": "com.android.server.am.BroadcastRecordTest" },
@@ -99,7 +99,7 @@
]
},
{
- "file_patterns": ["Broadcast"],
+ "file_patterns": ["Broadcast.*"],
"name": "CtsBroadcastTestCases",
"options": [
{ "exclude-annotation": "androidx.test.filters.LargeTest" },
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f61737e..67166b8 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -61,7 +61,6 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
-import android.app.Dialog;
import android.app.IStopUserCallback;
import android.app.IUserSwitchObserver;
import android.app.KeyguardManager;
@@ -555,12 +554,6 @@
// This user is already stopping, doesn't count.
continue;
}
- if (userId == UserHandle.USER_SYSTEM) {
- // We only count system user as running when it is not a pure system user.
- if (UserInfo.isSystemOnly(userId)) {
- continue;
- }
- }
runningUsers.add(userId);
}
return runningUsers;
@@ -1683,6 +1676,7 @@
R.anim.screen_user_exit, R.anim.screen_user_enter);
t.traceEnd();
}
+ dismissUserSwitchDialog(); // so that we don't hold a reference to mUserSwitchingDialog
boolean needStart = false;
boolean updateUmState = false;
@@ -1869,6 +1863,8 @@
boolean success = startUser(targetUserId, USER_START_MODE_FOREGROUND);
if (!success) {
mInjector.getWindowManager().setSwitchingUser(false);
+ mTargetUserId = UserHandle.USER_NULL;
+ dismissUserSwitchDialog();
}
}
@@ -2017,6 +2013,10 @@
return true;
}
+ private void dismissUserSwitchDialog() {
+ mInjector.dismissUserSwitchingDialog();
+ }
+
private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
// The dialog will show and then initiate the user switch by calling startUserInForeground
mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second,
@@ -3468,6 +3468,9 @@
private UserManagerService mUserManager;
private UserManagerInternal mUserManagerInternal;
private Handler mHandler;
+ private final Object mUserSwitchingDialogLock = new Object();
+ @GuardedBy("mUserSwitchingDialogLock")
+ private UserSwitchingDialog mUserSwitchingDialog;
Injector(ActivityManagerService service) {
mService = service;
@@ -3643,6 +3646,15 @@
mService.mCpHelper.installEncryptionUnawareProviders(userId);
}
+ void dismissUserSwitchingDialog() {
+ synchronized (mUserSwitchingDialogLock) {
+ if (mUserSwitchingDialog != null) {
+ mUserSwitchingDialog.dismiss();
+ mUserSwitchingDialog = null;
+ }
+ }
+ }
+
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
if (mService.mContext.getPackageManager()
@@ -3653,10 +3665,13 @@
Slogf.w(TAG, "Showing user switch dialog on UserController, it could cause a race "
+ "condition if it's shown by CarSystemUI as well");
}
- final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
- toUser, true /* above system */, switchingFromSystemUserMessage,
- switchingToSystemUserMessage);
- d.show();
+ synchronized (mUserSwitchingDialogLock) {
+ dismissUserSwitchingDialog();
+ mUserSwitchingDialog = new UserSwitchingDialog(mService, mService.mContext,
+ fromUser, toUser, true /* above system */, switchingFromSystemUserMessage,
+ switchingToSystemUserMessage);
+ mUserSwitchingDialog.show();
+ }
}
void reportGlobalUsageEvent(int event) {
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 7a6603d..a5651bf 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -95,9 +95,7 @@
R.layout.user_switching_dialog, null);
String viewMessage = null;
- if (UserManager.isSplitSystemUser() && mNewUser.id == UserHandle.USER_SYSTEM) {
- viewMessage = res.getString(R.string.user_logging_out_message, mOldUser.name);
- } else if (UserManager.isDeviceInDemoMode(mContext)) {
+ if (UserManager.isDeviceInDemoMode(mContext)) {
if (mOldUser.isDemo()) {
viewMessage = res.getString(R.string.demo_restarting_message);
} else {
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
index 908cb3f..684d6a0 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
@@ -17,6 +17,8 @@
package com.android.server.app;
import static android.Manifest.permission.MANAGE_GAME_ACTIVITY;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER;
+import static android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE;
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
@@ -34,7 +36,6 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.games.CreateGameSessionRequest;
@@ -51,7 +52,6 @@
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost.SurfacePackage;
-import android.view.WindowManager;
import android.window.ScreenCapture;
import com.android.internal.annotations.GuardedBy;
@@ -61,6 +61,7 @@
import com.android.internal.infra.ServiceConnector.ServiceLifecycleCallbacks;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.util.ScreenshotRequest;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener;
@@ -863,8 +864,6 @@
Slog.w(TAG, "Could not get bitmap for id: " + taskId);
callback.complete(GameScreenshotResult.createInternalErrorResult());
} else {
- final Bundle bundle = ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(
- bitmap);
final RunningTaskInfo runningTaskInfo =
mGameTaskInfoProvider.getRunningTaskInfo(taskId);
if (runningTaskInfo == null) {
@@ -879,11 +878,17 @@
callback.complete(GameScreenshotResult.createSuccessResult());
}
};
- mScreenshotHelper.provideScreenshot(bundle, crop, Insets.NONE, taskId,
- mUserHandle.getIdentifier(), gameSessionRecord.getComponentName(),
- WindowManager.ScreenshotSource.SCREENSHOT_OTHER,
- BackgroundThread.getHandler(),
- completionConsumer);
+ ScreenshotRequest request = new ScreenshotRequest.Builder(
+ TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER)
+ .setTopComponent(gameSessionRecord.getComponentName())
+ .setTaskId(taskId)
+ .setUserId(mUserHandle.getIdentifier())
+ .setBitmap(bitmap)
+ .setBoundsOnScreen(crop)
+ .setInsets(Insets.NONE)
+ .build();
+ mScreenshotHelper.takeScreenshot(
+ request, BackgroundThread.getHandler(), completionConsumer);
}
});
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 9877ed3..21bd7bc 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1718,8 +1718,9 @@
mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS);
} catch (Exception e) {
Log.e(TAG, "Exception acquiring wakelock", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- Binder.restoreCallingIdentity(identity);
}
if (MESSAGES_MUTE_MUSIC.contains(msg)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c794b04..92a9f46 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -908,9 +908,6 @@
private final SoundDoseHelper mSoundDoseHelper;
- @GuardedBy("mSettingsLock")
- private int mCurrentImeUid;
-
private final Object mSupportedSystemUsagesLock = new Object();
@GuardedBy("mSupportedSystemUsagesLock")
private @AttributeSystemUsage int[] mSupportedSystemUsages =
@@ -2856,10 +2853,14 @@
super.getPreferredDevicesForStrategy_enforcePermission();
List<AudioDeviceAttributes> devices = new ArrayList<>();
+ int status = AudioSystem.SUCCESS;
final long identity = Binder.clearCallingIdentity();
- final int status = AudioSystem.getDevicesForRoleAndStrategy(
- strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
- Binder.restoreCallingIdentity(identity);
+ try {
+ status = AudioSystem.getDevicesForRoleAndStrategy(
+ strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
if (status != AudioSystem.SUCCESS) {
Log.e(TAG, String.format("Error %d in getPreferredDeviceForStrategy(%d)",
status, strategy));
@@ -3045,10 +3046,14 @@
super.getPreferredDevicesForCapturePreset_enforcePermission();
List<AudioDeviceAttributes> devices = new ArrayList<>();
+ int status = AudioSystem.SUCCESS;
final long identity = Binder.clearCallingIdentity();
- final int status = AudioSystem.getDevicesForRoleAndCapturePreset(
- capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
- Binder.restoreCallingIdentity(identity);
+ try {
+ status = AudioSystem.getDevicesForRoleAndCapturePreset(
+ capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
if (status != AudioSystem.SUCCESS) {
Log.e(TAG, String.format("Error %d in getPreferredDeviceForCapturePreset(%d)",
status, capturePreset));
@@ -3653,11 +3658,14 @@
}
final long identity = Binder.clearCallingIdentity();
- mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
- isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
- getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
- isStreamMute(AudioSystem.STREAM_MUSIC));
- Binder.restoreCallingIdentity(identity);
+ try {
+ mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
+ isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
+ getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
+ isStreamMute(AudioSystem.STREAM_MUSIC));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
private int getNewRingerMode(int stream, int index, int flags) {
@@ -3782,7 +3790,7 @@
VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(),
- index/*val1*/, flags/*val2*/, callingPackage));
+ index, flags, callingPackage + ", user " + ActivityManager.getCurrentUser()));
vgs.setVolumeIndex(index, flags);
@@ -3803,7 +3811,7 @@
@Nullable
private AudioVolumeGroup getAudioVolumeGroupById(int volumeGroupId) {
- for (final AudioVolumeGroup avg : AudioVolumeGroup.getAudioVolumeGroups()) {
+ for (AudioVolumeGroup avg : AudioVolumeGroup.getAudioVolumeGroups()) {
if (avg.getId() == volumeGroupId) {
return avg;
}
@@ -3819,14 +3827,15 @@
super.getVolumeIndexForAttributes_enforcePermission();
Objects.requireNonNull(attr, "attr must not be null");
- final int volumeGroup =
- AudioProductStrategy.getVolumeGroupIdForAudioAttributes(
- attr, /* fallbackOnDefault= */false);
- if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
- throw new IllegalArgumentException("No volume group for attributes " + attr);
+ synchronized (VolumeStreamState.class) {
+ int volumeGroup = AudioProductStrategy.getVolumeGroupIdForAudioAttributes(
+ attr, /* fallbackOnDefault= */false);
+ if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
+ throw new IllegalArgumentException("No volume group for attributes " + attr);
+ }
+ VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
+ return vgs.isMuted() ? vgs.getMinIndex() : vgs.getVolumeIndex();
}
- final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
- return vgs.getVolumeIndex();
}
@android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
@@ -4984,26 +4993,26 @@
if (getCurrentUserId() == userId || userId == android.os.Process.SYSTEM_UID) {
final boolean currentMute = mAudioSystem.isMicrophoneMuted();
final long identity = Binder.clearCallingIdentity();
- final int ret = mAudioSystem.muteMicrophone(muted);
-
- // update cache with the real state independently from what was set
- mMicMuteFromSystemCached = mAudioSystem.isMicrophoneMuted();
- if (ret != AudioSystem.AUDIO_STATUS_OK) {
- Log.e(TAG, "Error changing mic mute state to " + muted + " current:"
- + mMicMuteFromSystemCached);
- }
-
- new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
- .setUid(userId)
- .set(MediaMetrics.Property.EVENT, "setMicrophoneMuteNoCallerCheck")
- .set(MediaMetrics.Property.MUTE, mMicMuteFromSystemCached
- ? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
- .set(MediaMetrics.Property.REQUEST, muted
- ? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE)
- .set(MediaMetrics.Property.STATUS, ret)
- .record();
-
try {
+ final int ret = mAudioSystem.muteMicrophone(muted);
+
+ // update cache with the real state independently from what was set
+ mMicMuteFromSystemCached = mAudioSystem.isMicrophoneMuted();
+ if (ret != AudioSystem.AUDIO_STATUS_OK) {
+ Log.e(TAG, "Error changing mic mute state to " + muted + " current:"
+ + mMicMuteFromSystemCached);
+ }
+
+ new MediaMetrics.Item(MediaMetrics.Name.AUDIO_MIC)
+ .setUid(userId)
+ .set(MediaMetrics.Property.EVENT, "setMicrophoneMuteNoCallerCheck")
+ .set(MediaMetrics.Property.MUTE, mMicMuteFromSystemCached
+ ? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
+ .set(MediaMetrics.Property.REQUEST, muted
+ ? MediaMetrics.Value.MUTE : MediaMetrics.Value.UNMUTE)
+ .set(MediaMetrics.Property.STATUS, ret)
+ .record();
+
// send the intent even if there was a failure to change the actual mute state:
// the AudioManager.setMicrophoneMute API doesn't have a return value to
// indicate if the call failed to successfully change the mute state, and receiving
@@ -5613,9 +5622,13 @@
+ mMode.get() + " requested mode: " + requestedMode);
}
if (mode != mMode.get() || force) {
+ int status = AudioSystem.SUCCESS;
final long identity = Binder.clearCallingIdentity();
- int status = mAudioSystem.setPhoneState(mode, uid);
- Binder.restoreCallingIdentity(identity);
+ try {
+ status = mAudioSystem.setPhoneState(mode, uid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
if (status == AudioSystem.AUDIO_STATUS_OK) {
if (DEBUG_MODE) {
Log.v(TAG, "onUpdateAudioMode: mode successfully set to " + mode);
@@ -5922,7 +5935,7 @@
mSoundDoseHelper.restoreMusicActiveMs();
mSoundDoseHelper.enforceSafeMediaVolumeIfActive(TAG);
- readVolumeGroupsSettings();
+ readVolumeGroupsSettings(userSwitch);
if (DEBUG_VOL) {
Log.d(TAG, "Restoring device volume behavior");
@@ -6022,17 +6035,22 @@
}
final long ident = Binder.clearCallingIdentity();
- boolean status =
- mDeviceBroker.setCommunicationDevice(cb, pid, device, eventSource);
- Binder.restoreCallingIdentity(ident);
- return status;
+ try {
+ return mDeviceBroker.setCommunicationDevice(cb, pid, device, eventSource);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
/** @see AudioManager#getCommunicationDevice() */
public int getCommunicationDevice() {
+ AudioDeviceInfo device = null;
final long ident = Binder.clearCallingIdentity();
- AudioDeviceInfo device = mDeviceBroker.getCommunicationDevice();
- Binder.restoreCallingIdentity(ident);
+ try {
+ device = mDeviceBroker.getCommunicationDevice();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
if (device == null) {
return 0;
}
@@ -6082,8 +6100,11 @@
? MediaMetrics.Value.ON : MediaMetrics.Value.OFF)
.record();
final long ident = Binder.clearCallingIdentity();
- mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
- Binder.restoreCallingIdentity(ident);
+ try {
+ mDeviceBroker.setSpeakerphoneOn(cb, pid, on, eventSource);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
/** @see AudioManager#isSpeakerphoneOn() */
@@ -6223,8 +6244,11 @@
return;
}
final long ident = Binder.clearCallingIdentity();
- mDeviceBroker.startBluetoothScoForClient(cb, pid, scoAudioMode, eventSource);
- Binder.restoreCallingIdentity(ident);
+ try {
+ mDeviceBroker.startBluetoothScoForClient(cb, pid, scoAudioMode, eventSource);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
mmi.record();
}
@@ -6240,8 +6264,11 @@
.append(") from u/pid:").append(uid).append("/")
.append(pid).toString();
final long ident = Binder.clearCallingIdentity();
- mDeviceBroker.stopBluetoothScoForClient(cb, pid, eventSource);
- Binder.restoreCallingIdentity(ident);
+ try {
+ mDeviceBroker.stopBluetoothScoForClient(cb, pid, eventSource);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_BLUETOOTH)
.setUid(uid)
.setPid(pid)
@@ -6530,8 +6557,11 @@
(TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
final long ident = Binder.clearCallingIdentity();
- IsInCall = telecomManager.isInCall();
- Binder.restoreCallingIdentity(ident);
+ try {
+ IsInCall = telecomManager.isInCall();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
int mode = mMode.get();
return (IsInCall
@@ -6671,10 +6701,13 @@
private void queueMsgUnderWakeLock(Handler handler, int msg,
int arg1, int arg2, Object obj, int delay) {
final long ident = Binder.clearCallingIdentity();
- // Always acquire the wake lock as AudioService because it is released by the
- // message handler.
- mAudioEventWakeLock.acquire();
- Binder.restoreCallingIdentity(ident);
+ try {
+ // Always acquire the wake lock as AudioService because it is released by the
+ // message handler.
+ mAudioEventWakeLock.acquire();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
}
@@ -7311,6 +7344,7 @@
try {
// if no valid attributes, this volume group is not controllable, throw exception
ensureValidAttributes(avg);
+ sVolumeGroupStates.append(avg.getId(), new VolumeGroupState(avg));
} catch (IllegalArgumentException e) {
// Volume Groups without attributes are not controllable through set/get volume
// using attributes. Do not append them.
@@ -7319,11 +7353,10 @@
}
continue;
}
- sVolumeGroupStates.append(avg.getId(), new VolumeGroupState(avg));
}
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- vgs.applyAllVolumes();
+ vgs.applyAllVolumes(/* userSwitch= */ false);
}
}
@@ -7336,14 +7369,22 @@
}
}
- private void readVolumeGroupsSettings() {
- if (DEBUG_VOL) {
- Log.v(TAG, "readVolumeGroupsSettings");
- }
- for (int i = 0; i < sVolumeGroupStates.size(); i++) {
- final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- vgs.readSettings();
- vgs.applyAllVolumes();
+ private void readVolumeGroupsSettings(boolean userSwitch) {
+ synchronized (mSettingsLock) {
+ synchronized (VolumeStreamState.class) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "readVolumeGroupsSettings userSwitch=" + userSwitch);
+ }
+ for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+ VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+ // as for STREAM_MUSIC, preserve volume from one user to the next.
+ if (!(userSwitch && vgs.isMusic())) {
+ vgs.clearIndexCache();
+ vgs.readSettings();
+ }
+ vgs.applyAllVolumes(userSwitch);
+ }
+ }
}
}
@@ -7354,7 +7395,7 @@
}
for (int i = 0; i < sVolumeGroupStates.size(); i++) {
final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- vgs.applyAllVolumes();
+ vgs.applyAllVolumes(false/*userSwitch*/);
}
}
@@ -7367,17 +7408,24 @@
}
}
+ private static boolean isCallStream(int stream) {
+ return stream == AudioSystem.STREAM_VOICE_CALL
+ || stream == AudioSystem.STREAM_BLUETOOTH_SCO;
+ }
+
// NOTE: Locking order for synchronized objects related to volume management:
// 1 mSettingsLock
- // 2 VolumeGroupState.class
+ // 2 VolumeStreamState.class
private class VolumeGroupState {
private final AudioVolumeGroup mAudioVolumeGroup;
private final SparseIntArray mIndexMap = new SparseIntArray(8);
private int mIndexMin;
private int mIndexMax;
- private int mLegacyStreamType = AudioSystem.STREAM_DEFAULT;
+ private boolean mHasValidStreamType = false;
private int mPublicStreamType = AudioSystem.STREAM_MUSIC;
private AudioAttributes mAudioAttributes = AudioProductStrategy.getDefaultAttributes();
+ private boolean mIsMuted = false;
+ private final String mSettingName;
// No API in AudioSystem to get a device from strategy or from attributes.
// Need a valid public stream type to use current API getDeviceForStream
@@ -7391,20 +7439,22 @@
Log.v(TAG, "VolumeGroupState for " + avg.toString());
}
// mAudioAttributes is the default at this point
- for (final AudioAttributes aa : avg.getAudioAttributes()) {
+ for (AudioAttributes aa : avg.getAudioAttributes()) {
if (!aa.equals(mAudioAttributes)) {
mAudioAttributes = aa;
break;
}
}
- final int[] streamTypes = mAudioVolumeGroup.getLegacyStreamTypes();
+ int[] streamTypes = mAudioVolumeGroup.getLegacyStreamTypes();
+ String streamSettingName = "";
if (streamTypes.length != 0) {
// Uses already initialized MIN / MAX if a stream type is attached to group
- mLegacyStreamType = streamTypes[0];
- for (final int streamType : streamTypes) {
+ for (int streamType : streamTypes) {
if (streamType != AudioSystem.STREAM_DEFAULT
&& streamType < AudioSystem.getNumStreamTypes()) {
mPublicStreamType = streamType;
+ mHasValidStreamType = true;
+ streamSettingName = System.VOLUME_SETTINGS_INT[mPublicStreamType];
break;
}
}
@@ -7414,10 +7464,10 @@
mIndexMin = AudioSystem.getMinVolumeIndexForAttributes(mAudioAttributes);
mIndexMax = AudioSystem.getMaxVolumeIndexForAttributes(mAudioAttributes);
} else {
- Log.e(TAG, "volume group: " + mAudioVolumeGroup.name()
+ throw new IllegalArgumentException("volume group: " + mAudioVolumeGroup.name()
+ " has neither valid attributes nor valid stream types assigned");
- return;
}
+ mSettingName = !streamSettingName.isEmpty() ? streamSettingName : ("volume_" + name());
// Load volume indexes from data base
readSettings();
}
@@ -7430,40 +7480,101 @@
return mAudioVolumeGroup.name();
}
+ /**
+ * Volume group with non null minimum index are considered as non mutable, thus
+ * bijectivity is broken with potential associated stream type.
+ * VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an
+ * app that has MODIFY_PHONE_STATE permission.
+ */
+ private boolean isVssMuteBijective(int stream) {
+ return isStreamAffectedByMute(stream)
+ && (getMinIndex() == (mStreamStates[stream].mIndexMin + 5) / 10)
+ && (getMinIndex() == 0 || isCallStream(stream));
+ }
+
+ private boolean isMutable() {
+ return mIndexMin == 0 || (mHasValidStreamType && isVssMuteBijective(mPublicStreamType));
+ }
+ /**
+ * Mute/unmute the volume group
+ * @param muted the new mute state
+ */
+ @GuardedBy("AudioService.VolumeStreamState.class")
+ public boolean mute(boolean muted) {
+ if (!isMutable()) {
+ // Non mutable volume group
+ if (DEBUG_VOL) {
+ Log.d(TAG, "invalid mute on unmutable volume group " + name());
+ }
+ return false;
+ }
+ boolean changed = (mIsMuted != muted);
+ // As for VSS, mute shall apply minIndex to all devices found in IndexMap and default.
+ if (changed) {
+ mIsMuted = muted;
+ applyAllVolumes(false /*userSwitch*/);
+ }
+ return changed;
+ }
+
+ public boolean isMuted() {
+ return mIsMuted;
+ }
+
public int getVolumeIndex() {
- return getIndex(getDeviceForVolume());
+ synchronized (VolumeStreamState.class) {
+ return getIndex(getDeviceForVolume());
+ }
}
public void setVolumeIndex(int index, int flags) {
- if (mUseFixedVolume) {
- return;
+ synchronized (VolumeStreamState.class) {
+ if (mUseFixedVolume) {
+ return;
+ }
+ setVolumeIndex(index, getDeviceForVolume(), flags);
}
- setVolumeIndex(index, getDeviceForVolume(), flags);
}
+ @GuardedBy("AudioService.VolumeStreamState.class")
private void setVolumeIndex(int index, int device, int flags) {
- // Set the volume index
- setVolumeIndexInt(index, device, flags);
-
- // Update local cache
- mIndexMap.put(device, index);
-
- // update data base - post a persist volume group msg
- sendMsg(mAudioHandler,
- MSG_PERSIST_VOLUME_GROUP,
- SENDMSG_QUEUE,
- device,
- 0,
- this,
- PERSIST_DELAY);
+ // Update cache & persist (muted by volume 0 shall be persisted)
+ updateVolumeIndex(index, device);
+ // setting non-zero volume for a muted stream unmutes the stream and vice versa,
+ boolean changed = mute(index == 0);
+ if (!changed) {
+ // Set the volume index only if mute operation is a no-op
+ index = getValidIndex(index);
+ setVolumeIndexInt(index, device, flags);
+ }
}
+ @GuardedBy("AudioService.VolumeStreamState.class")
+ public void updateVolumeIndex(int index, int device) {
+ // Filter persistency if already exist and the index has not changed
+ if (mIndexMap.indexOfKey(device) < 0 || mIndexMap.get(device) != index) {
+ // Update local cache
+ mIndexMap.put(device, getValidIndex(index));
+
+ // update data base - post a persist volume group msg
+ sendMsg(mAudioHandler,
+ MSG_PERSIST_VOLUME_GROUP,
+ SENDMSG_QUEUE,
+ device,
+ 0,
+ this,
+ PERSIST_DELAY);
+ }
+ }
+
+ @GuardedBy("AudioService.VolumeStreamState.class")
private void setVolumeIndexInt(int index, int device, int flags) {
// Reflect mute state of corresponding stream by forcing index to 0 if muted
// Only set audio policy BT SCO stream volume to 0 when the stream is actually muted.
// This allows RX path muting by the audio HAL only when explicitly muted but not when
// index is just set to 0 to repect BT requirements
- if (mStreamStates[mPublicStreamType].isFullyMuted()) {
+ if (mHasValidStreamType && isVssMuteBijective(mPublicStreamType)
+ && mStreamStates[mPublicStreamType].isFullyMuted()) {
index = 0;
} else if (mPublicStreamType == AudioSystem.STREAM_BLUETOOTH_SCO && index == 0) {
index = 1;
@@ -7472,18 +7583,16 @@
AudioSystem.setVolumeIndexForAttributes(mAudioAttributes, index, device);
}
- public int getIndex(int device) {
- synchronized (VolumeGroupState.class) {
- int index = mIndexMap.get(device, -1);
- // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
- return (index != -1) ? index : mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
- }
+ @GuardedBy("AudioService.VolumeStreamState.class")
+ private int getIndex(int device) {
+ int index = mIndexMap.get(device, -1);
+ // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
+ return (index != -1) ? index : mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
}
- public boolean hasIndexForDevice(int device) {
- synchronized (VolumeGroupState.class) {
- return (mIndexMap.get(device, -1) != -1);
- }
+ @GuardedBy("AudioService.VolumeStreamState.class")
+ private boolean hasIndexForDevice(int device) {
+ return (mIndexMap.get(device, -1) != -1);
}
public int getMaxIndex() {
@@ -7494,55 +7603,108 @@
return mIndexMin;
}
- private boolean isValidLegacyStreamType() {
- return (mLegacyStreamType != AudioSystem.STREAM_DEFAULT)
- && (mLegacyStreamType < mStreamStates.length);
+ private boolean isValidStream(int stream) {
+ return (stream != AudioSystem.STREAM_DEFAULT) && (stream < mStreamStates.length);
}
- public void applyAllVolumes() {
- synchronized (VolumeGroupState.class) {
- int deviceForStream = AudioSystem.DEVICE_NONE;
- int volumeIndexForStream = 0;
- if (isValidLegacyStreamType()) {
- // Prevent to apply settings twice when group is associated to public stream
- deviceForStream = getDeviceForStream(mLegacyStreamType);
- volumeIndexForStream = getStreamVolume(mLegacyStreamType);
- }
+ public boolean isMusic() {
+ return mHasValidStreamType && mPublicStreamType == AudioSystem.STREAM_MUSIC;
+ }
+
+ public void applyAllVolumes(boolean userSwitch) {
+ String caller = "from vgs";
+ synchronized (VolumeStreamState.class) {
// apply device specific volumes first
- int index;
for (int i = 0; i < mIndexMap.size(); i++) {
- final int device = mIndexMap.keyAt(i);
+ int device = mIndexMap.keyAt(i);
+ int index = mIndexMap.valueAt(i);
+ boolean synced = false;
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
- index = mIndexMap.valueAt(i);
- if (device == deviceForStream && volumeIndexForStream == index) {
- continue;
+ for (int stream : getLegacyStreamTypes()) {
+ if (isValidStream(stream)) {
+ boolean streamMuted = mStreamStates[stream].mIsMuted;
+ int deviceForStream = getDeviceForStream(stream);
+ int indexForStream =
+ (mStreamStates[stream].getIndex(deviceForStream) + 5) / 10;
+ if (device == deviceForStream) {
+ if (indexForStream == index && (isMuted() == streamMuted)
+ && isVssMuteBijective(stream)) {
+ synced = true;
+ continue;
+ }
+ if (indexForStream != index) {
+ mStreamStates[stream].setIndex(index * 10, device, caller,
+ true /*hasModifyAudioSettings*/);
+ }
+ if ((isMuted() != streamMuted) && isVssMuteBijective(stream)) {
+ mStreamStates[stream].mute(isMuted());
+ }
+ }
+ }
}
- if (DEBUG_VOL) {
- Log.v(TAG, "applyAllVolumes: restore index " + index + " for group "
- + mAudioVolumeGroup.name() + " and device "
- + AudioSystem.getOutputDeviceName(device));
+ if (!synced) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "applyAllVolumes: apply index " + index + ", group "
+ + mAudioVolumeGroup.name() + " and device "
+ + AudioSystem.getOutputDeviceName(device));
+ }
+ setVolumeIndexInt(isMuted() ? 0 : index, device, 0 /*flags*/);
}
- setVolumeIndexInt(index, device, 0 /*flags*/);
}
}
// apply default volume last: by convention , default device volume will be used
// by audio policy manager if no explicit volume is present for a given device type
- index = getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
- if (DEBUG_VOL) {
- Log.v(TAG, "applyAllVolumes: restore default device index " + index
- + " for group " + mAudioVolumeGroup.name());
- }
- if (isValidLegacyStreamType()) {
- int defaultStreamIndex = (mStreamStates[mLegacyStreamType]
- .getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5) / 10;
- if (defaultStreamIndex == index) {
- return;
+ int index = getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
+ boolean synced = false;
+ int deviceForVolume = getDeviceForVolume();
+ boolean forceDeviceSync = userSwitch && (mIndexMap.indexOfKey(deviceForVolume) < 0);
+ for (int stream : getLegacyStreamTypes()) {
+ if (isValidStream(stream)) {
+ boolean streamMuted = mStreamStates[stream].mIsMuted;
+ int defaultStreamIndex = (mStreamStates[stream].getIndex(
+ AudioSystem.DEVICE_OUT_DEFAULT) + 5) / 10;
+ if (forceDeviceSync) {
+ mStreamStates[stream].setIndex(index * 10, deviceForVolume, caller,
+ true /*hasModifyAudioSettings*/);
+ }
+ if (defaultStreamIndex == index && (isMuted() == streamMuted)
+ && isVssMuteBijective(stream)) {
+ synced = true;
+ continue;
+ }
+ if (defaultStreamIndex != index) {
+ mStreamStates[stream].setIndex(
+ index * 10, AudioSystem.DEVICE_OUT_DEFAULT, caller,
+ true /*hasModifyAudioSettings*/);
+ }
+ if ((isMuted() != streamMuted) && isVssMuteBijective(stream)) {
+ mStreamStates[stream].mute(isMuted());
+ }
}
}
- setVolumeIndexInt(index, AudioSystem.DEVICE_OUT_DEFAULT, 0 /*flags*/);
+ if (!synced) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "applyAllVolumes: apply default device index " + index
+ + ", group " + mAudioVolumeGroup.name());
+ }
+ setVolumeIndexInt(
+ isMuted() ? 0 : index, AudioSystem.DEVICE_OUT_DEFAULT, 0 /*flags*/);
+ }
+ if (forceDeviceSync) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "applyAllVolumes: forceDeviceSync index " + index
+ + ", device " + AudioSystem.getOutputDeviceName(deviceForVolume)
+ + ", group " + mAudioVolumeGroup.name());
+ }
+ setVolumeIndexInt(isMuted() ? 0 : index, deviceForVolume, 0);
+ }
}
}
+ public void clearIndexCache() {
+ mIndexMap.clear();
+ }
+
private void persistVolumeGroup(int device) {
if (mUseFixedVolume) {
return;
@@ -7556,16 +7718,14 @@
boolean success = mSettings.putSystemIntForUser(mContentResolver,
getSettingNameForDevice(device),
getIndex(device),
- UserHandle.USER_CURRENT);
+ isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
if (!success) {
Log.e(TAG, "persistVolumeGroup failed for group " + mAudioVolumeGroup.name());
}
}
public void readSettings() {
- synchronized (VolumeGroupState.class) {
- // First clear previously loaded (previous user?) settings
- mIndexMap.clear();
+ synchronized (VolumeStreamState.class) {
// force maximum volume on all streams if fixed volume property is set
if (mUseFixedVolume) {
mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
@@ -7580,7 +7740,8 @@
int index;
String name = getSettingNameForDevice(device);
index = mSettings.getSystemIntForUser(
- mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+ mContentResolver, name, defaultIndex,
+ isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
if (index == -1) {
continue;
}
@@ -7598,6 +7759,7 @@
}
}
+ @GuardedBy("AudioService.VolumeStreamState.class")
private int getValidIndex(int index) {
if (index < mIndexMin) {
return mIndexMin;
@@ -7608,15 +7770,17 @@
}
public @NonNull String getSettingNameForDevice(int device) {
- final String suffix = AudioSystem.getOutputDeviceName(device);
+ String suffix = AudioSystem.getOutputDeviceName(device);
if (suffix.isEmpty()) {
- return mAudioVolumeGroup.name();
+ return mSettingName;
}
- return mAudioVolumeGroup.name() + "_" + AudioSystem.getOutputDeviceName(device);
+ return mSettingName + "_" + AudioSystem.getOutputDeviceName(device);
}
private void dump(PrintWriter pw) {
pw.println("- VOLUME GROUP " + mAudioVolumeGroup.name() + ":");
+ pw.print(" Muted: ");
+ pw.println(mIsMuted);
pw.print(" Min: ");
pw.println(mIndexMin);
pw.print(" Max: ");
@@ -7626,9 +7790,9 @@
if (i > 0) {
pw.print(", ");
}
- final int device = mIndexMap.keyAt(i);
+ int device = mIndexMap.keyAt(i);
pw.print(Integer.toHexString(device));
- final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
+ String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
: AudioSystem.getOutputDeviceName(device);
if (!deviceName.isEmpty()) {
pw.print(" (");
@@ -7641,7 +7805,7 @@
pw.println();
pw.print(" Devices: ");
int n = 0;
- final int devices = getDeviceForVolume();
+ int devices = getDeviceForVolume();
for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
if ((devices & device) == device) {
if (n++ > 0) {
@@ -7650,6 +7814,10 @@
pw.print(AudioSystem.getOutputDeviceName(device));
}
}
+ pw.println();
+ pw.print(" Streams: ");
+ Arrays.stream(getLegacyStreamTypes())
+ .forEach(stream -> pw.print(AudioSystem.streamToString(stream) + " "));
}
}
@@ -9939,6 +10107,55 @@
"com.android.server.audio", "AudioService");
}
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public float getRs2Value() {
+ super.getRs2Value_enforcePermission();
+ return mSoundDoseHelper.getRs2Value();
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void setRs2Value(float rs2Value) {
+ super.setRs2Value_enforcePermission();
+ mSoundDoseHelper.setRs2Value(rs2Value);
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public float getCsd() {
+ super.getCsd_enforcePermission();
+ return mSoundDoseHelper.getCsd();
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void setCsd(float csd) {
+ super.setCsd_enforcePermission();
+ mSoundDoseHelper.setCsd(csd);
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void forceUseFrameworkMel(boolean useFrameworkMel) {
+ super.forceUseFrameworkMel_enforcePermission();
+ mSoundDoseHelper.forceUseFrameworkMel(useFrameworkMel);
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
+ super.forceComputeCsdOnAllDevices_enforcePermission();
+ mSoundDoseHelper.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
+ }
+
+ @Override
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_AUDIO_SYSTEM_SETTINGS)
+ public boolean isCsdEnabled() {
+ super.isCsdEnabled_enforcePermission();
+ return mSoundDoseHelper.isCsdEnabled();
+ }
+
//==========================================================================================
// Hdmi CEC:
// - System audio mode:
@@ -10290,7 +10507,6 @@
+ " FromRestrictions=" + mMicMuteFromRestrictions
+ " FromApi=" + mMicMuteFromApi
+ " from system=" + mMicMuteFromSystemCached);
- pw.print(" mCurrentImeUid="); pw.println(mCurrentImeUid);
dumpAccessibilityServiceUids(pw);
dumpAssistantServicesUids(pw);
@@ -10425,6 +10641,15 @@
}
@Override
+ @Nullable
+ public IVolumeController getVolumeController() {
+ enforceVolumeController("get the volume controller");
+ if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
+
+ return mVolumeController.getController();
+ }
+
+ @Override
public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
enforceVolumeController("notify about volume controller visibility");
@@ -10469,6 +10694,10 @@
mVisible = false;
}
+ public IVolumeController getController() {
+ return mController;
+ }
+
public void loadSettings(ContentResolver cr) {
mLongPressTimeout = mSettings.getSecureIntForUser(cr,
Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
@@ -11558,13 +11787,16 @@
int callingUid = Binder.getCallingUid();
int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
final long identity = Binder.clearCallingIdentity();
- synchronized (mPlaybackMonitor) {
- int result = mAudioSystem.setAllowedCapturePolicy(callingUid, flags);
- if (result == AudioSystem.AUDIO_STATUS_OK) {
- mPlaybackMonitor.setAllowedCapturePolicy(callingUid, capturePolicy);
+ try {
+ synchronized (mPlaybackMonitor) {
+ int result = mAudioSystem.setAllowedCapturePolicy(callingUid, flags);
+ if (result == AudioSystem.AUDIO_STATUS_OK) {
+ mPlaybackMonitor.setAllowedCapturePolicy(callingUid, capturePolicy);
+ }
+ return result;
}
+ } finally {
Binder.restoreCallingIdentity(identity);
- return result;
}
}
@@ -11575,9 +11807,11 @@
public int getAllowedCapturePolicy() {
int callingUid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
- int capturePolicy = mPlaybackMonitor.getAllowedCapturePolicy(callingUid);
- Binder.restoreCallingIdentity(identity);
- return capturePolicy;
+ try {
+ return mPlaybackMonitor.getAllowedCapturePolicy(callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
//======================
@@ -11719,8 +11953,11 @@
}
}
final long identity = Binder.clearCallingIdentity();
- mAudioSystem.registerPolicyMixes(mMixes, false);
- Binder.restoreCallingIdentity(identity);
+ try {
+ mAudioSystem.registerPolicyMixes(mMixes, false);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
synchronized (mAudioPolicies) {
mAudioPolicies.remove(mPolicyCallback.asBinder());
}
@@ -11779,9 +12016,12 @@
@AudioSystem.AudioSystemError int connectMixes() {
final long identity = Binder.clearCallingIdentity();
- int status = mAudioSystem.registerPolicyMixes(mMixes, true);
- Binder.restoreCallingIdentity(identity);
- return status;
+ try {
+ return mAudioSystem.registerPolicyMixes(mMixes, true);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
}
int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 919b850..bc61b37 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -53,6 +53,7 @@
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -70,9 +71,6 @@
/*package*/ static final String ACTION_CHECK_MUSIC_ACTIVE =
"com.android.server.audio.action.CHECK_MUSIC_ACTIVE";
- /** Flag to enable/disable the sound dose computation. */
- private static final boolean USE_CSD_FOR_SAFE_HEARING = false;
-
// mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
// It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
// or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
@@ -96,8 +94,6 @@
private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
private static final int REQUEST_CODE_CHECK_MUSIC_ACTIVE = 1;
- private static final float CUSTOM_RS2_VALUE = 90;
-
// timeouts for the CSD warnings, -1 means no timeout (dialog must be ack'd by user)
private static final int CSD_WARNING_TIMEOUT_MS_DOSE_1X = 7000;
private static final int CSD_WARNING_TIMEOUT_MS_DOSE_5X = 5000;
@@ -233,6 +229,94 @@
initCsd();
}
+ float getRs2Value() {
+ if (!mEnableCsd) {
+ return 0.f;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ return mSoundDose.getOutputRs2();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while getting the RS2 exposure value", e);
+ return 0.f;
+ }
+ }
+
+ void setRs2Value(float rs2Value) {
+ if (!mEnableCsd) {
+ return;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ mSoundDose.setOutputRs2(rs2Value);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while setting the RS2 exposure value", e);
+ }
+ }
+
+ float getCsd() {
+ if (!mEnableCsd) {
+ return -1.f;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ return mSoundDose.getCsd();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while getting the CSD value", e);
+ return -1.f;
+ }
+ }
+
+ void setCsd(float csd) {
+ if (!mEnableCsd) {
+ return;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ final SoundDoseRecord record = new SoundDoseRecord();
+ record.timestamp = System.currentTimeMillis();
+ record.value = csd;
+ final SoundDoseRecord[] recordArray = new SoundDoseRecord[] { record };
+ mSoundDose.resetCsd(csd, recordArray);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while setting the CSD value", e);
+ }
+ }
+
+ void forceUseFrameworkMel(boolean useFrameworkMel) {
+ if (!mEnableCsd) {
+ return;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ mSoundDose.forceUseFrameworkMel(useFrameworkMel);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while forcing the internal MEL computation", e);
+ }
+ }
+
+ void forceComputeCsdOnAllDevices(boolean computeCsdOnAllDevices) {
+ if (!mEnableCsd) {
+ return;
+ }
+
+ Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+ try {
+ mSoundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while forcing CSD computation on all devices", e);
+ }
+ }
+
+ boolean isCsdEnabled() {
+ return mEnableCsd;
+ }
+
/*package*/ int safeMediaVolumeIndex(int device) {
if (!mSafeMediaVolumeDevices.contains(device)) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
@@ -293,7 +377,7 @@
|| (AudioService.mStreamVolumeAlias[streamType] != AudioSystem.STREAM_MUSIC)
|| (!mSafeMediaVolumeDevices.contains(device))
|| (index <= safeMediaVolumeIndex(device))
- || USE_CSD_FOR_SAFE_HEARING;
+ || mEnableCsd;
}
/*package*/ boolean willDisplayWarningAfterCheckVolume(int streamType, int index, int device,
@@ -329,7 +413,7 @@
/*package*/ void scheduleMusicActiveCheck() {
synchronized (mSafeMediaVolumeStateLock) {
cancelMusicActiveCheck();
- if (!USE_CSD_FOR_SAFE_HEARING) {
+ if (!mEnableCsd) {
mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
REQUEST_CODE_CHECK_MUSIC_ACTIVE,
new Intent(ACTION_CHECK_MUSIC_ACTIVE),
@@ -460,14 +544,13 @@
private void initCsd() {
synchronized (mSafeMediaVolumeStateLock) {
- if (USE_CSD_FOR_SAFE_HEARING) {
+ if (mEnableCsd) {
Log.v(TAG, "Initializing sound dose");
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
try {
if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
- mSoundDose.setOutputRs2(CUSTOM_RS2_VALUE);
if (mCurrentCsd != 0.f) {
Log.d(TAG, "Resetting the saved sound dose value " + mCurrentCsd);
SoundDoseRecord[] records = mDoseRecords.toArray(
@@ -502,7 +585,7 @@
// The persisted state is either "disabled" or "active": this is the state applied
// next time we boot and cannot be "inactive"
int persistedState;
- if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !USE_CSD_FOR_SAFE_HEARING) {
+ if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !mEnableCsd) {
persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
// The state can already be "inactive" here if the user has forced it before
// the 30 seconds timeout for forced configuration. In this case we don't reset
diff --git a/services/core/java/com/android/server/backup/AppGrammaticalGenderBackupHelper.java b/services/core/java/com/android/server/backup/AppGrammaticalGenderBackupHelper.java
new file mode 100644
index 0000000..9e8db6e
--- /dev/null
+++ b/services/core/java/com/android/server/backup/AppGrammaticalGenderBackupHelper.java
@@ -0,0 +1,66 @@
+/*
+ * 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.backup;
+
+import static android.app.backup.BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
+
+import android.annotation.UserIdInt;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.BlobBackupHelper;
+import android.os.ParcelFileDescriptor;
+
+import com.android.server.LocalServices;
+import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
+
+public class AppGrammaticalGenderBackupHelper extends BlobBackupHelper {
+ private static final int BLOB_VERSION = 1;
+ private static final String KEY_APP_GENDER = "app_gender";
+
+ private final @UserIdInt int mUserId;
+ private final GrammaticalInflectionManagerInternal mGrammarInflectionManagerInternal;
+
+ public AppGrammaticalGenderBackupHelper(int userId) {
+ super(BLOB_VERSION, KEY_APP_GENDER);
+ mUserId = userId;
+ mGrammarInflectionManagerInternal = LocalServices.getService(
+ GrammaticalInflectionManagerInternal.class);
+ }
+
+ @Override
+ public void performBackup(ParcelFileDescriptor oldStateFd, BackupDataOutput data,
+ ParcelFileDescriptor newStateFd) {
+ // Only backup the gender data if e2e encryption is present
+ if ((data.getTransportFlags() & FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED) == 0) {
+ return;
+ }
+
+ super.performBackup(oldStateFd, data, newStateFd);
+ }
+
+ @Override
+ protected byte[] getBackupPayload(String key) {
+ return KEY_APP_GENDER.equals(key) && mGrammarInflectionManagerInternal != null ?
+ mGrammarInflectionManagerInternal.getBackupPayload(mUserId) : null;
+ }
+
+ @Override
+ protected void applyRestoredPayload(String key, byte[] payload) {
+ if (KEY_APP_GENDER.equals(key) && mGrammarInflectionManagerInternal != null) {
+ mGrammarInflectionManagerInternal.stageAndApplyRestoredPayload(payload, mUserId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 59d8afa..b18be3c 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -58,6 +58,7 @@
private static final String SLICES_HELPER = "slices";
private static final String PEOPLE_HELPER = "people";
private static final String APP_LOCALES_HELPER = "app_locales";
+ private static final String APP_GENDER_HELPER = "app_gender";
// These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME
// are also used in the full-backup file format, so must not change unless steps are
@@ -105,6 +106,7 @@
addHelper(SLICES_HELPER, new SliceBackupHelper(this));
addHelper(PEOPLE_HELPER, new PeopleBackupHelper(mUserId));
addHelper(APP_LOCALES_HELPER, new AppSpecificLocalesBackupHelper(mUserId));
+ addHelper(APP_GENDER_HELPER, new AppGrammaticalGenderBackupHelper(mUserId));
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 2ac8b43..513b3e3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -230,6 +230,10 @@
session.getSession().onPointerDown(pc.pointerId, (int) pc.x, (int) pc.y, pc.minor,
pc.major);
}
+
+ if (getListener() != null) {
+ getListener().onUdfpsPointerDown(getSensorId());
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send pointer down", e);
}
@@ -246,6 +250,10 @@
} else {
session.getSession().onPointerUp(pc.pointerId);
}
+
+ if (getListener() != null) {
+ getListener().onUdfpsPointerUp(getSensorId());
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send pointer up", e);
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceState.java b/services/core/java/com/android/server/devicestate/DeviceState.java
index 42fe9d8..a589313 100644
--- a/services/core/java/com/android/server/devicestate/DeviceState.java
+++ b/services/core/java/com/android/server/devicestate/DeviceState.java
@@ -64,10 +64,27 @@
*/
public static final int FLAG_EMULATED_ONLY = 1 << 2;
+ /**
+ * This flag indicates that the corresponding state should be automatically canceled when the
+ * requesting app is no longer on top. The app is considered not on top when (1) the top
+ * activity in the system is from a different app, (2) the device is in sleep mode, or
+ * (3) the keyguard shows up.
+ */
+ public static final int FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP = 1 << 3;
+
+ /**
+ * This flag indicates that the corresponding state should be disabled when the device is
+ * overheating and reaching the critical status.
+ */
+ public static final int FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL = 1 << 4;
+
/** @hide */
@IntDef(prefix = {"FLAG_"}, flag = true, value = {
FLAG_CANCEL_OVERRIDE_REQUESTS,
- FLAG_APP_INACCESSIBLE
+ FLAG_APP_INACCESSIBLE,
+ FLAG_EMULATED_ONLY,
+ FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeviceStateFlags {}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index c856cab..064cd2d 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -33,6 +33,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.TaskStackListener;
import android.content.Context;
import android.hardware.devicestate.DeviceStateInfo;
import android.hardware.devicestate.DeviceStateManager;
@@ -176,6 +177,12 @@
@NonNull
private final SystemPropertySetter mSystemPropertySetter;
+ @VisibleForTesting
+ TaskStackListener mOverrideRequestTaskStackListener = new OverrideRequestTaskStackListener();
+ @VisibleForTesting
+ ActivityTaskManagerInternal.ScreenObserver mOverrideRequestScreenObserver =
+ new OverrideRequestScreenObserver();
+
public DeviceStateManagerService(@NonNull Context context) {
this(context, DeviceStatePolicy.Provider
.fromResources(context.getResources())
@@ -215,6 +222,9 @@
readStatesAvailableForRequestFromApps();
mFoldedDeviceStates = readFoldedStates();
}
+
+ mActivityTaskManagerInternal.registerTaskStackListener(mOverrideRequestTaskStackListener);
+ mActivityTaskManagerInternal.registerScreenObserver(mOverrideRequestScreenObserver);
}
@VisibleForTesting
@@ -842,9 +852,7 @@
* @param state state that is being requested.
*/
private void assertCanRequestDeviceState(int callingPid, int state) {
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp == null || topApp.getPid() != callingPid
- || !isStateAvailableForAppRequests(state)) {
+ if (!isTopApp(callingPid) || !isStateAvailableForAppRequests(state)) {
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
"Permission required to request device state, "
+ "or the call must come from the top app "
@@ -859,14 +867,18 @@
* @param callingPid Process ID that is requesting this state change
*/
private void assertCanControlDeviceState(int callingPid) {
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp == null || topApp.getPid() != callingPid) {
+ if (!isTopApp(callingPid)) {
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
"Permission required to request device state, "
+ "or the call must come from the top app.");
}
}
+ private boolean isTopApp(int callingPid) {
+ final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
+ return topApp != null && topApp.getPid() == callingPid;
+ }
+
private boolean isStateAvailableForAppRequests(int state) {
synchronized (mLock) {
return mDeviceStatesAvailableForAppRequests.contains(state);
@@ -1185,4 +1197,52 @@
}
}
}
+
+ @GuardedBy("mLock")
+ private boolean shouldCancelOverrideRequestWhenRequesterNotOnTop() {
+ if (mActiveOverride.isEmpty()) {
+ return false;
+ }
+ int identifier = mActiveOverride.get().getRequestedState();
+ DeviceState deviceState = mDeviceStates.get(identifier);
+ return deviceState.hasFlag(DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
+ }
+
+ private class OverrideRequestTaskStackListener extends TaskStackListener {
+ @Override
+ public void onTaskStackChanged() throws RemoteException {
+ synchronized (mLock) {
+ if (!shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
+ return;
+ }
+
+ OverrideRequest request = mActiveOverride.get();
+ if (!isTopApp(request.getPid())) {
+ mOverrideRequestController.cancelRequest(request);
+ }
+ }
+ }
+ }
+
+ private class OverrideRequestScreenObserver implements
+ ActivityTaskManagerInternal.ScreenObserver {
+
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+ synchronized (mLock) {
+ if (!isAwake && shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
+ mOverrideRequestController.cancelRequest(mActiveOverride.get());
+ }
+ }
+ }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ synchronized (mLock) {
+ if (isShowing && shouldCancelOverrideRequestWhenRequesterNotOnTop()) {
+ mOverrideRequestController.cancelRequest(mActiveOverride.get());
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 06b99f8..d558e69 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -109,7 +109,6 @@
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
@@ -261,13 +260,6 @@
final SparseArray<Pair<IVirtualDevice, DisplayWindowPolicyController>>
mDisplayWindowPolicyControllers = new SparseArray<>();
- /**
- * Map of every internal primary display device {@link HighBrightnessModeMetadata}s indexed by
- * {@link DisplayDevice#mUniqueId}.
- */
- public final ArrayMap<String, HighBrightnessModeMetadata> mHighBrightnessModeMetadataMap =
- new ArrayMap<>();
-
// List of all currently registered display adapters.
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
@@ -1648,16 +1640,7 @@
DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
- + display.getDisplayIdLocked());
- return;
- }
-
- final String uniqueId = device.getUniqueId();
- HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
- dpc.onDisplayChanged(hbmMetadata);
+ dpc.onDisplayChanged();
}
}
@@ -1715,15 +1698,7 @@
final int displayId = display.getDisplayIdLocked();
final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
- + display.getDisplayIdLocked());
- return;
- }
- final String uniqueId = device.getUniqueId();
- HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
- dpc.onDisplayChanged(hbmMetadata);
+ dpc.onDisplayChanged();
}
}
@@ -2676,31 +2651,6 @@
mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
}
- private HighBrightnessModeMetadata getHighBrightnessModeMetadata(LogicalDisplay display) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
- + display.getDisplayIdLocked());
- return null;
- }
-
- // HBM brightness mode is only applicable to internal physical displays.
- if (display.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
- return null;
- }
-
- final String uniqueId = device.getUniqueId();
-
- if (mHighBrightnessModeMetadataMap.containsKey(uniqueId)) {
- return mHighBrightnessModeMetadataMap.get(uniqueId);
- }
-
- // HBM Time info not present. Create a new one for this physical display.
- HighBrightnessModeMetadata hbmInfo = new HighBrightnessModeMetadata();
- mHighBrightnessModeMetadataMap.put(uniqueId, hbmInfo);
- return hbmInfo;
- }
-
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
private void addDisplayPowerControllerLocked(LogicalDisplay display) {
if (mPowerHandler == null) {
@@ -2716,23 +2666,17 @@
display, mSyncRoot);
final DisplayPowerControllerInterface displayPowerController;
- // If display is internal and has a HighBrightnessModeMetadata mapping, use that.
- // Or create a new one and use that.
- // We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to
- // displayPowerController, so the hbm info can be correctly associated
- // with the corresponding displaydevice.
- HighBrightnessModeMetadata hbmMetadata = getHighBrightnessModeMetadata(display);
if (DeviceConfig.getBoolean("display_manager",
"use_newly_structured_display_power_controller", true)) {
displayPowerController = new DisplayPowerController2(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
- () -> handleBrightnessChange(display), hbmMetadata);
+ () -> handleBrightnessChange(display));
} else {
displayPowerController = new DisplayPowerController(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
- () -> handleBrightnessChange(display), hbmMetadata);
+ () -> handleBrightnessChange(display));
}
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 142ec68..cdaa3d0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -388,7 +388,6 @@
private float[] mNitsRange;
private final HighBrightnessModeController mHbmController;
- private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
private final BrightnessThrottler mBrightnessThrottler;
@@ -506,14 +505,13 @@
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
- Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
+ Runnable onBrightnessChangeRunnable) {
mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock();
mLogicalDisplay = logicalDisplay;
mDisplayId = mLogicalDisplay.getDisplayIdLocked();
mTag = "DisplayPowerController[" + mDisplayId + "]";
- mHighBrightnessModeMetadata = hbmMetadata;
mSuspendBlockerIdUnfinishedBusiness = getSuspendBlockerUnfinishedBusinessId(mDisplayId);
mSuspendBlockerIdOnStateChanged = getSuspendBlockerOnStateChangedId(mDisplayId);
mSuspendBlockerIdProxPositive = getSuspendBlockerProxPositiveId(mDisplayId);
@@ -792,7 +790,7 @@
* Make sure DisplayManagerService.mSyncRoot is held when this is called
*/
@Override
- public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
+ public void onDisplayChanged() {
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
if (device == null) {
Slog.wtf(mTag, "Display Device is null in DisplayPowerController for display: "
@@ -814,7 +812,7 @@
mUniqueDisplayId = uniqueId;
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
- loadFromDisplayDeviceConfig(token, info, hbmMetadata);
+ loadFromDisplayDeviceConfig(token, info);
/// Since the underlying display-device changed, we really don't know the
// last command that was sent to change it's state. Lets assume it is unknown so
@@ -866,8 +864,7 @@
}
}
- private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
- HighBrightnessModeMetadata hbmMetadata) {
+ private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
// All properties that depend on the associated DisplayDevice and the DDC must be
// updated here.
loadBrightnessRampRates();
@@ -880,7 +877,6 @@
mBrightnessRampIncreaseMaxTimeMillis,
mBrightnessRampDecreaseMaxTimeMillis);
}
- mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
mDisplayDeviceConfig.getHighBrightnessModeData(),
new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
@@ -1965,7 +1961,7 @@
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.update();
}
- }, mHighBrightnessModeMetadata, mContext);
+ }, mContext);
}
private BrightnessThrottler createBrightnessThrottlerLocked() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 96342f3..da59cca 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -328,7 +328,6 @@
private float[] mNitsRange;
private final HighBrightnessModeController mHbmController;
- private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;
private final BrightnessThrottler mBrightnessThrottler;
@@ -433,7 +432,7 @@
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
- Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
+ Runnable onBrightnessChangeRunnable) {
mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock();
@@ -449,7 +448,6 @@
mDisplayPowerProximityStateController = mInjector.getDisplayPowerProximityStateController(
mWakelockController, mDisplayDeviceConfig, mHandler.getLooper(),
() -> updatePowerState(), mDisplayId, mSensorManager);
- mHighBrightnessModeMetadata = hbmMetadata;
mDisplayStateController = new DisplayStateController(mDisplayPowerProximityStateController);
mTag = "DisplayPowerController2[" + mDisplayId + "]";
@@ -709,7 +707,7 @@
* Make sure DisplayManagerService.mSyncRoot lock is held when this is called
*/
@Override
- public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
+ public void onDisplayChanged() {
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
if (device == null) {
Slog.wtf(mTag, "Display Device is null in DisplayPowerController2 for display: "
@@ -723,7 +721,6 @@
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
final boolean isEnabled = mLogicalDisplay.isEnabledLocked();
final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
-
mHandler.post(() -> {
boolean changed = false;
if (mDisplayDevice != device) {
@@ -732,7 +729,7 @@
mUniqueDisplayId = uniqueId;
mDisplayStatsId = mUniqueDisplayId.hashCode();
mDisplayDeviceConfig = config;
- loadFromDisplayDeviceConfig(token, info, hbmMetadata);
+ loadFromDisplayDeviceConfig(token, info);
mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config);
// Since the underlying display-device changed, we really don't know the
@@ -781,8 +778,7 @@
}
}
- private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
- HighBrightnessModeMetadata hbmMetadata) {
+ private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
// All properties that depend on the associated DisplayDevice and the DDC must be
// updated here.
loadBrightnessRampRates();
@@ -794,7 +790,6 @@
mBrightnessRampIncreaseMaxTimeMillis,
mBrightnessRampDecreaseMaxTimeMillis);
}
- mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
mDisplayDeviceConfig.getHighBrightnessModeData(),
new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
@@ -1747,7 +1742,7 @@
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.update();
}
- }, mHighBrightnessModeMetadata, mContext);
+ }, mContext);
}
private BrightnessThrottler createBrightnessThrottlerLocked() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index 7b019846..e750ee2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -31,14 +31,10 @@
public interface DisplayPowerControllerInterface {
/**
- * Notified when the display is changed.
- * We use this to apply any changes that might be needed
+ * Notified when the display is changed. We use this to apply any changes that might be needed
* when displays get swapped on foldable devices.
- * We also pass the High brightness mode metadata like
- * remaining time and hbm events for the corresponding
- * physical display, to update the values correctly.
*/
- void onDisplayChanged(HighBrightnessModeMetadata hbmInfo);
+ void onDisplayChanged();
/**
* Unregisters all listeners and interrupts all running threads; halting future work.
diff --git a/services/core/java/com/android/server/display/HbmEvent.java b/services/core/java/com/android/server/display/HbmEvent.java
deleted file mode 100644
index 5675e2f..0000000
--- a/services/core/java/com/android/server/display/HbmEvent.java
+++ /dev/null
@@ -1,46 +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.server.display;
-
-
-/**
- * Represents an event in which High Brightness Mode was enabled.
- */
-class HbmEvent {
- private long mStartTimeMillis;
- private long mEndTimeMillis;
-
- HbmEvent(long startTimeMillis, long endTimeMillis) {
- this.mStartTimeMillis = startTimeMillis;
- this.mEndTimeMillis = endTimeMillis;
- }
-
- public long getStartTimeMillis() {
- return mStartTimeMillis;
- }
-
- public long getEndTimeMillis() {
- return mEndTimeMillis;
- }
-
- @Override
- public String toString() {
- return "HbmEvent: {startTimeMillis:" + mStartTimeMillis + ", endTimeMillis: "
- + mEndTimeMillis + "}, total: "
- + ((mEndTimeMillis - mStartTimeMillis) / 1000) + "]";
- }
-}
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 2c843a4..f98c7df 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -105,23 +105,30 @@
private int mHbmStatsState = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;
/**
- * If HBM is currently running, this is the start time and set of all events,
- * for the current HBM session.
+ * If HBM is currently running, this is the start time for the current HBM session.
*/
- private HighBrightnessModeMetadata mHighBrightnessModeMetadata = null;
+ private long mRunningStartTimeMillis = -1;
+
+ /**
+ * Queue of previous HBM-events ordered from most recent to least recent.
+ * Meant to store only the events that fall into the most recent
+ * {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}.
+ */
+ private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>();
+
HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
String displayUniqueId, float brightnessMin, float brightnessMax,
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
- Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
+ Runnable hbmChangeCallback, Context context) {
this(new Injector(), handler, width, height, displayToken, displayUniqueId, brightnessMin,
- brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, hbmMetadata, context);
+ brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, context);
}
@VisibleForTesting
HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax,
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
- Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
+ Runnable hbmChangeCallback, Context context) {
mInjector = injector;
mContext = context;
mClock = injector.getClock();
@@ -130,7 +137,6 @@
mBrightnessMin = brightnessMin;
mBrightnessMax = brightnessMax;
mHbmChangeCallback = hbmChangeCallback;
- mHighBrightnessModeMetadata = hbmMetadata;
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mRecalcRunnable = this::recalculateTimeAllowance;
@@ -216,22 +222,19 @@
// If we are starting or ending a high brightness mode session, store the current
// session in mRunningStartTimeMillis, or the old one in mEvents.
- final long runningStartTime = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
- final boolean wasHbmDrainingAvailableTime = runningStartTime != -1;
+ final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1;
final boolean shouldHbmDrainAvailableTime = mBrightness > mHbmData.transitionPoint
&& !mIsHdrLayerPresent;
if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) {
final long currentTime = mClock.uptimeMillis();
if (shouldHbmDrainAvailableTime) {
- mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
+ mRunningStartTimeMillis = currentTime;
} else {
- final HbmEvent hbmEvent = new HbmEvent(runningStartTime, currentTime);
- mHighBrightnessModeMetadata.addHbmEvent(hbmEvent);
- mHighBrightnessModeMetadata.setRunningStartTimeMillis(-1);
+ mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
+ mRunningStartTimeMillis = -1;
if (DEBUG) {
- Slog.d(TAG, "New HBM event: "
- + mHighBrightnessModeMetadata.getHbmEventQueue().peekFirst());
+ Slog.d(TAG, "New HBM event: " + mEvents.peekFirst());
}
}
}
@@ -257,10 +260,6 @@
mSettingsObserver.stopObserving();
}
- void setHighBrightnessModeMetadata(HighBrightnessModeMetadata hbmInfo) {
- mHighBrightnessModeMetadata = hbmInfo;
- }
-
void resetHbmData(int width, int height, IBinder displayToken, String displayUniqueId,
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg) {
mWidth = width;
@@ -317,22 +316,20 @@
pw.println(" mBrightnessMax=" + mBrightnessMax);
pw.println(" remainingTime=" + calculateRemainingTime(mClock.uptimeMillis()));
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
- pw.println(" mRunningStartTimeMillis="
- + TimeUtils.formatUptime(mHighBrightnessModeMetadata.getRunningStartTimeMillis()));
+ pw.println(" mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
pw.println(" mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
pw.println(" width*height=" + mWidth + "*" + mHeight);
pw.println(" mEvents=");
final long currentTime = mClock.uptimeMillis();
long lastStartTime = currentTime;
- long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
- if (runningStartTimeMillis != -1) {
- lastStartTime = dumpHbmEvent(pw, new HbmEvent(runningStartTimeMillis, currentTime));
+ if (mRunningStartTimeMillis != -1) {
+ lastStartTime = dumpHbmEvent(pw, new HbmEvent(mRunningStartTimeMillis, currentTime));
}
- for (HbmEvent event : mHighBrightnessModeMetadata.getHbmEventQueue()) {
- if (lastStartTime > event.getEndTimeMillis()) {
+ for (HbmEvent event : mEvents) {
+ if (lastStartTime > event.endTimeMillis) {
pw.println(" event: [normal brightness]: "
- + TimeUtils.formatDuration(lastStartTime - event.getEndTimeMillis()));
+ + TimeUtils.formatDuration(lastStartTime - event.endTimeMillis));
}
lastStartTime = dumpHbmEvent(pw, event);
}
@@ -341,12 +338,12 @@
}
private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
- final long duration = event.getEndTimeMillis() - event.getStartTimeMillis();
+ final long duration = event.endTimeMillis - event.startTimeMillis;
pw.println(" event: ["
- + TimeUtils.formatUptime(event.getStartTimeMillis()) + ", "
- + TimeUtils.formatUptime(event.getEndTimeMillis()) + "] ("
+ + TimeUtils.formatUptime(event.startTimeMillis) + ", "
+ + TimeUtils.formatUptime(event.endTimeMillis) + "] ("
+ TimeUtils.formatDuration(duration) + ")");
- return event.getStartTimeMillis();
+ return event.startTimeMillis;
}
private boolean isCurrentlyAllowed() {
@@ -375,15 +372,13 @@
// First, lets see how much time we've taken for any currently running
// session of HBM.
- long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
- if (runningStartTimeMillis > 0) {
- if (runningStartTimeMillis > currentTime) {
+ if (mRunningStartTimeMillis > 0) {
+ if (mRunningStartTimeMillis > currentTime) {
Slog.e(TAG, "Start time set to the future. curr: " + currentTime
- + ", start: " + runningStartTimeMillis);
- mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
- runningStartTimeMillis = currentTime;
+ + ", start: " + mRunningStartTimeMillis);
+ mRunningStartTimeMillis = currentTime;
}
- timeAlreadyUsed = currentTime - runningStartTimeMillis;
+ timeAlreadyUsed = currentTime - mRunningStartTimeMillis;
}
if (DEBUG) {
@@ -392,19 +387,18 @@
// Next, lets iterate through the history of previous sessions and add those times.
final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
- Iterator<HbmEvent> it = mHighBrightnessModeMetadata.getHbmEventQueue().iterator();
+ Iterator<HbmEvent> it = mEvents.iterator();
while (it.hasNext()) {
final HbmEvent event = it.next();
// If this event ended before the current Timing window, discard forever and ever.
- if (event.getEndTimeMillis() < windowstartTimeMillis) {
+ if (event.endTimeMillis < windowstartTimeMillis) {
it.remove();
continue;
}
- final long startTimeMillis = Math.max(event.getStartTimeMillis(),
- windowstartTimeMillis);
- timeAlreadyUsed += event.getEndTimeMillis() - startTimeMillis;
+ final long startTimeMillis = Math.max(event.startTimeMillis, windowstartTimeMillis);
+ timeAlreadyUsed += event.endTimeMillis - startTimeMillis;
}
if (DEBUG) {
@@ -431,18 +425,17 @@
// Calculate the time at which we want to recalculate mIsTimeAvailable in case a lux or
// brightness change doesn't happen before then.
long nextTimeout = -1;
- final ArrayDeque<HbmEvent> hbmEvents = mHighBrightnessModeMetadata.getHbmEventQueue();
if (mBrightness > mHbmData.transitionPoint) {
// if we're in high-lux now, timeout when we run out of allowed time.
nextTimeout = currentTime + remainingTime;
- } else if (!mIsTimeAvailable && hbmEvents.size() > 0) {
+ } else if (!mIsTimeAvailable && mEvents.size() > 0) {
// If we are not allowed...timeout when the oldest event moved outside of the timing
// window by at least minTime. Basically, we're calculating the soonest time we can
// get {@code timeMinMillis} back to us.
final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
- final HbmEvent lastEvent = hbmEvents.peekLast();
+ final HbmEvent lastEvent = mEvents.peekLast();
final long startTimePlusMinMillis =
- Math.max(windowstartTimeMillis, lastEvent.getStartTimeMillis())
+ Math.max(windowstartTimeMillis, lastEvent.startTimeMillis)
+ mHbmData.timeMinMillis;
final long timeWhenMinIsGainedBack =
currentTime + (startTimePlusMinMillis - windowstartTimeMillis) - remainingTime;
@@ -466,10 +459,9 @@
+ ", mUnthrottledBrightness: " + mUnthrottledBrightness
+ ", mThrottlingReason: "
+ BrightnessInfo.briMaxReasonToString(mThrottlingReason)
- + ", RunningStartTimeMillis: "
- + mHighBrightnessModeMetadata.getRunningStartTimeMillis()
+ + ", RunningStartTimeMillis: " + mRunningStartTimeMillis
+ ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
- + ", events: " + hbmEvents);
+ + ", events: " + mEvents);
}
if (nextTimeout != -1) {
@@ -596,6 +588,25 @@
}
}
+ /**
+ * Represents an event in which High Brightness Mode was enabled.
+ */
+ private static class HbmEvent {
+ public long startTimeMillis;
+ public long endTimeMillis;
+
+ HbmEvent(long startTimeMillis, long endTimeMillis) {
+ this.startTimeMillis = startTimeMillis;
+ this.endTimeMillis = endTimeMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "[Event: {" + startTimeMillis + ", " + endTimeMillis + "}, total: "
+ + ((endTimeMillis - startTimeMillis) / 1000) + "]";
+ }
+ }
+
@VisibleForTesting
class HdrListener extends SurfaceControlHdrLayerInfoListener {
@Override
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeMetadata.java b/services/core/java/com/android/server/display/HighBrightnessModeMetadata.java
deleted file mode 100644
index 37234ff..0000000
--- a/services/core/java/com/android/server/display/HighBrightnessModeMetadata.java
+++ /dev/null
@@ -1,58 +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.server.display;
-
-import java.util.ArrayDeque;
-
-
-/**
- * Represents High Brightness Mode metadata associated
- * with a specific internal physical display.
- * Required for separately storing data like time information,
- * and related events when display was in HBM mode per
- * physical internal display.
- */
-class HighBrightnessModeMetadata {
- /**
- * Queue of previous HBM-events ordered from most recent to least recent.
- * Meant to store only the events that fall into the most recent
- * {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}.
- */
- private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>();
-
- /**
- * If HBM is currently running, this is the start time for the current HBM session.
- */
- private long mRunningStartTimeMillis = -1;
-
- public long getRunningStartTimeMillis() {
- return mRunningStartTimeMillis;
- }
-
- public void setRunningStartTimeMillis(long setTime) {
- mRunningStartTimeMillis = setTime;
- }
-
- public ArrayDeque<HbmEvent> getHbmEventQueue() {
- return mEvents;
- }
-
- public void addHbmEvent(HbmEvent hbmEvent) {
- mEvents.addFirst(hbmEvent);
- }
-}
-
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index bb342ff..5087caa 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -177,6 +177,7 @@
private Layout mCurrentLayout = null;
private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
+ private int mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE;
private boolean mBootCompleted = false;
private boolean mInteractive;
@@ -373,6 +374,12 @@
ipw.println("mDeviceStatesOnWhichToWakeUp=" + mDeviceStatesOnWhichToWakeUp);
ipw.println("mDeviceStatesOnWhichToSleep=" + mDeviceStatesOnWhichToSleep);
ipw.println("mInteractive=" + mInteractive);
+ ipw.println("mBootCompleted=" + mBootCompleted);
+
+ ipw.println();
+ ipw.println("mDeviceState=" + mDeviceState);
+ ipw.println("mPendingDeviceState=" + mPendingDeviceState);
+ ipw.println("mDeviceStateToBeAppliedAfterBoot=" + mDeviceStateToBeAppliedAfterBoot);
final int logicalDisplayCount = mLogicalDisplays.size();
ipw.println();
@@ -403,10 +410,6 @@
}
void setDeviceStateLocked(int state, boolean isOverrideActive) {
- Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
- + ", interactive=" + mInteractive + ", mBootCompleted=" + mBootCompleted);
- mPendingDeviceState = state;
-
if (!mBootCompleted) {
// The boot animation might still be in progress, we do not want to switch states now
// as the boot animation would end up with an incorrect size.
@@ -414,14 +417,19 @@
Slog.d(TAG, "Postponing transition to state: " + mPendingDeviceState
+ " until boot is completed");
}
+ mDeviceStateToBeAppliedAfterBoot = state;
return;
}
+ Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
+ + ", interactive=" + mInteractive + ", mBootCompleted=" + mBootCompleted);
// As part of a state transition, we may need to turn off some displays temporarily so that
// the transition is smooth. Plus, on some devices, only one internal displays can be
// on at a time. We use LogicalDisplay.setIsInTransition to mark a display that needs to be
// temporarily turned off.
resetLayoutLocked(mDeviceState, state, /* transitionValue= */ true);
+ mPendingDeviceState = state;
+ mDeviceStateToBeAppliedAfterBoot = DeviceStateManager.INVALID_DEVICE_STATE;
final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
mInteractive, mBootCompleted);
final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState,
@@ -468,8 +476,9 @@
void onBootCompleted() {
synchronized (mSyncRoot) {
mBootCompleted = true;
- if (mPendingDeviceState != DeviceStateManager.INVALID_DEVICE_STATE) {
- setDeviceStateLocked(mPendingDeviceState, /* isOverrideActive= */ false);
+ if (mDeviceStateToBeAppliedAfterBoot != DeviceStateManager.INVALID_DEVICE_STATE) {
+ setDeviceStateLocked(mDeviceStateToBeAppliedAfterBoot,
+ /* isOverrideActive= */ false);
}
}
}
@@ -524,7 +533,8 @@
@VisibleForTesting
boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isOverrideActive,
boolean isInteractive, boolean isBootCompleted) {
- return mDeviceStatesOnWhichToSleep.get(pendingState)
+ return currentState != DeviceStateManager.INVALID_DEVICE_STATE
+ && mDeviceStatesOnWhichToSleep.get(pendingState)
&& !mDeviceStatesOnWhichToSleep.get(currentState)
&& !isOverrideActive
&& isInteractive && isBootCompleted;
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index e5357f6..c1780a3 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -16,9 +16,6 @@
package com.android.server.dreams;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-
-import android.app.ActivityTaskManager;
import android.app.BroadcastOptions;
import android.content.ComponentName;
import android.content.Context;
@@ -65,7 +62,6 @@
private final Context mContext;
private final Handler mHandler;
private final Listener mListener;
- private final ActivityTaskManager mActivityTaskManager;
private final Intent mDreamingStartedIntent = new Intent(Intent.ACTION_DREAMING_STARTED)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -93,7 +89,6 @@
mContext = context;
mHandler = handler;
mListener = listener;
- mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
mCloseNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
mCloseNotificationShadeIntent.putExtra("reason", "dream");
}
@@ -277,9 +272,6 @@
mSentStartBroadcast = false;
}
- mActivityTaskManager.removeRootTasksWithActivityTypes(
- new int[] {ACTIVITY_TYPE_DREAM});
-
mListener.onDreamStopped(dream.mToken);
}
} finally {
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
new file mode 100644
index 0000000..5be0735
--- /dev/null
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionBackupHelper.java
@@ -0,0 +1,193 @@
+/*
+ * 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.grammaticalinflection;
+
+import android.app.backup.BackupManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.time.Clock;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GrammaticalInflectionBackupHelper {
+ private static final String TAG = GrammaticalInflectionBackupHelper.class.getSimpleName();
+ private static final String SYSTEM_BACKUP_PACKAGE_KEY = "android";
+ // Stage data would be deleted on reboot since it's stored in memory. So it's retained until
+ // retention period OR next reboot, whichever happens earlier.
+ private static final Duration STAGE_DATA_RETENTION_PERIOD = Duration.ofDays(3);
+
+ private final SparseArray<StagedData> mCache = new SparseArray<>();
+ private final Object mCacheLock = new Object();
+ private final PackageManager mPackageManager;
+ private final GrammaticalInflectionService mGrammaticalGenderService;
+ private final Clock mClock;
+
+ static class StagedData {
+ final long mCreationTimeMillis;
+ final HashMap<String, Integer> mPackageStates;
+
+ StagedData(long creationTimeMillis) {
+ mCreationTimeMillis = creationTimeMillis;
+ mPackageStates = new HashMap<>();
+ }
+ }
+
+ public GrammaticalInflectionBackupHelper(GrammaticalInflectionService grammaticalGenderService,
+ PackageManager packageManager) {
+ mGrammaticalGenderService = grammaticalGenderService;
+ mPackageManager = packageManager;
+ mClock = Clock.systemUTC();
+ }
+
+ public byte[] getBackupPayload(int userId) {
+ synchronized (mCacheLock) {
+ cleanStagedDataForOldEntries();
+ }
+
+ HashMap<String, Integer> pkgGenderInfo = new HashMap<>();
+ for (ApplicationInfo appInfo : mPackageManager.getInstalledApplicationsAsUser(
+ PackageManager.ApplicationInfoFlags.of(0), userId)) {
+ int gender = mGrammaticalGenderService.getApplicationGrammaticalGender(
+ appInfo.packageName, userId);
+ if (gender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ pkgGenderInfo.put(appInfo.packageName, gender);
+ }
+ }
+
+ if (!pkgGenderInfo.isEmpty()) {
+ return convertToByteArray(pkgGenderInfo);
+ } else {
+ return null;
+ }
+ }
+
+ public void stageAndApplyRestoredPayload(byte[] payload, int userId) {
+ synchronized (mCacheLock) {
+ cleanStagedDataForOldEntries();
+
+ HashMap<String, Integer> pkgInfo = readFromByteArray(payload);
+ if (pkgInfo.isEmpty()) {
+ return;
+ }
+
+ StagedData stagedData = new StagedData(mClock.millis());
+ for (Map.Entry<String, Integer> info : pkgInfo.entrySet()) {
+ // If app installed, restore immediately, otherwise put it in cache.
+ if (isPackageInstalledForUser(info.getKey(), userId)) {
+ if (!hasSetBeforeRestoring(info.getKey(), userId)) {
+ mGrammaticalGenderService.setRequestedApplicationGrammaticalGender(
+ info.getKey(), userId, info.getValue());
+ }
+ } else {
+ if (info.getValue() != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ stagedData.mPackageStates.put(info.getKey(), info.getValue());
+ }
+ }
+ }
+
+ mCache.append(userId, stagedData);
+ }
+ }
+
+ private boolean hasSetBeforeRestoring(String pkgName, int userId) {
+ return mGrammaticalGenderService.getApplicationGrammaticalGender(pkgName, userId)
+ != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ }
+
+ public void onPackageAdded(String packageName, int uid) {
+ synchronized (mCacheLock) {
+ int userId = UserHandle.getUserId(uid);
+ StagedData cache = mCache.get(userId);
+ if (cache != null && cache.mPackageStates.containsKey(packageName)) {
+ int grammaticalGender = cache.mPackageStates.get(packageName);
+ if (grammaticalGender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ mGrammaticalGenderService.setRequestedApplicationGrammaticalGender(
+ packageName, userId, grammaticalGender);
+ }
+ }
+ }
+ }
+
+ public void onPackageDataCleared() {
+ notifyBackupManager();
+ }
+
+ public void onPackageRemoved() {
+ notifyBackupManager();
+ }
+
+ public static void notifyBackupManager() {
+ BackupManager.dataChanged(SYSTEM_BACKUP_PACKAGE_KEY);
+ }
+
+ private byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) {
+ try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final ObjectOutputStream objStream = new ObjectOutputStream(out)) {
+ objStream.writeObject(pkgGenderInfo);
+ return out.toByteArray();
+ } catch (IOException e) {
+ Log.e(TAG, "cannot convert payload to byte array.", e);
+ return null;
+ }
+ }
+
+ private HashMap<String, Integer> readFromByteArray(byte[] payload) {
+ HashMap<String, Integer> data = new HashMap<>();
+
+ try (ByteArrayInputStream byteIn = new ByteArrayInputStream(payload);
+ ObjectInputStream in = new ObjectInputStream(byteIn)) {
+ data = (HashMap<String, Integer>) in.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ Log.e(TAG, "cannot convert payload to HashMap.", e);
+ e.printStackTrace();
+ }
+ return data;
+ }
+
+ private void cleanStagedDataForOldEntries() {
+ for (int i = 0; i < mCache.size(); i++) {
+ int userId = mCache.keyAt(i);
+ StagedData stagedData = mCache.get(userId);
+ if (stagedData.mCreationTimeMillis
+ < mClock.millis() - STAGE_DATA_RETENTION_PERIOD.toMillis()) {
+ mCache.remove(userId);
+ }
+ }
+ }
+
+ private boolean isPackageInstalledForUser(String packageName, int userId) {
+ PackageInfo pkgInfo = null;
+ try {
+ pkgInfo = mPackageManager.getPackageInfoAsUser(packageName, /* flags= */ 0, userId);
+ } catch (PackageManager.NameNotFoundException e) {
+ // The package is not installed
+ }
+ return pkgInfo != null;
+ }
+}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
new file mode 100644
index 0000000..1f59b57
--- /dev/null
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
@@ -0,0 +1,41 @@
+/*
+ * 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.grammaticalinflection;
+
+import android.annotation.Nullable;
+
+/**
+ * System-server internal interface to the {@link android.app.GrammaticalInflectionManager}.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class GrammaticalInflectionManagerInternal {
+ /**
+ * Returns the app-gender to be backed up as a data-blob.
+ */
+ public abstract @Nullable byte[] getBackupPayload(int userId);
+
+ /**
+ * Restores the app-gender that were previously backed up.
+ *
+ * <p>This method will parse the input data blob and restore the gender for apps which are
+ * present on the device. It will stage the gender data for the apps which are not installed
+ * at the time this is called, to be referenced later when the app is installed.
+ */
+ public abstract void stageAndApplyRestoredPayload(byte[] payload, int userId);
+}
+
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionPackageMonitor.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionPackageMonitor.java
new file mode 100644
index 0000000..268bf66
--- /dev/null
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionPackageMonitor.java
@@ -0,0 +1,42 @@
+/*
+ * 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.grammaticalinflection;
+
+import com.android.internal.content.PackageMonitor;
+
+public class GrammaticalInflectionPackageMonitor extends PackageMonitor {
+ private GrammaticalInflectionBackupHelper mBackupHelper;
+
+ GrammaticalInflectionPackageMonitor(GrammaticalInflectionBackupHelper backupHelper) {
+ mBackupHelper = backupHelper;
+ }
+
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ mBackupHelper.onPackageAdded(packageName, uid);
+ }
+
+ @Override
+ public void onPackageDataCleared(String packageName, int uid) {
+ mBackupHelper.onPackageDataCleared();
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ mBackupHelper.onPackageRemoved();
+ }
+}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 6cfe921..1a357ee 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -18,9 +18,12 @@
import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
+import android.annotation.Nullable;
import android.app.IGrammaticalInflectionManager;
import android.content.Context;
+import android.os.Binder;
import android.os.IBinder;
+import android.os.Process;
import android.os.SystemProperties;
import com.android.server.LocalServices;
@@ -34,6 +37,7 @@
*/
public class GrammaticalInflectionService extends SystemService {
+ private final GrammaticalInflectionBackupHelper mBackupHelper;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
private static final String GRAMMATICAL_INFLECTION_ENABLED =
"i18n.grammatical_Inflection.enabled";
@@ -46,17 +50,20 @@
* </p>
*
* @param context The system server context.
- *
* @hide
*/
public GrammaticalInflectionService(Context context) {
super(context);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+ mBackupHelper = new GrammaticalInflectionBackupHelper(
+ this, context.getPackageManager());
}
@Override
public void onStart() {
publishBinderService(Context.GRAMMATICAL_INFLECTION_SERVICE, mService);
+ LocalServices.addService(GrammaticalInflectionManagerInternal.class,
+ new GrammaticalInflectionManagerInternalImpl());
}
private final IBinder mService = new IGrammaticalInflectionManager.Stub() {
@@ -68,7 +75,40 @@
}
};
- private void setRequestedApplicationGrammaticalGender(
+ private final class GrammaticalInflectionManagerInternalImpl
+ extends GrammaticalInflectionManagerInternal {
+
+ @Override
+ @Nullable
+ public byte[] getBackupPayload(int userId) {
+ checkCallerIsSystem();
+ return mBackupHelper.getBackupPayload(userId);
+ }
+
+ @Override
+ public void stageAndApplyRestoredPayload(byte[] payload, int userId) {
+ mBackupHelper.stageAndApplyRestoredPayload(payload, userId);
+ }
+
+ private void checkCallerIsSystem() {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("Caller is not system.");
+ }
+ }
+ }
+
+ protected int getApplicationGrammaticalGender(String appPackageName, int userId) {
+ final ActivityTaskManagerInternal.PackageConfig appConfig =
+ mActivityTaskManagerInternal.getApplicationConfig(appPackageName, userId);
+
+ if (appConfig == null || appConfig.mGrammaticalGender == null) {
+ return GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ } else {
+ return appConfig.mGrammaticalGender;
+ }
+ }
+
+ protected void setRequestedApplicationGrammaticalGender(
String appPackageName, int userId, int gender) {
if (!SystemProperties.getBoolean(GRAMMATICAL_INFLECTION_ENABLED, true)) {
return;
diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java
index 684b5f1..adcda0a 100644
--- a/services/core/java/com/android/server/incident/PendingReports.java
+++ b/services/core/java/com/android/server/incident/PendingReports.java
@@ -16,15 +16,20 @@
package com.android.server.incident;
+import static android.permission.PermissionManager.PERMISSION_GRANTED;
+
+import android.Manifest;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.Build;
import android.os.Handler;
import android.os.IIncidentAuthListener;
import android.os.IncidentManager;
@@ -32,6 +37,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.permission.PermissionManager;
import android.util.Log;
import java.io.FileDescriptor;
@@ -55,6 +61,7 @@
private final Context mContext;
private final PackageManager mPackageManager;
private final AppOpsManager mAppOpsManager;
+ private final PermissionManager mPermissionManager;
//
// All fields below must be protected by mLock
@@ -126,6 +133,7 @@
mContext = context;
mPackageManager = context.getPackageManager();
mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mPermissionManager = context.getSystemService(PermissionManager.class);
}
/**
@@ -297,6 +305,35 @@
return;
}
+ // Only with userdebug/eng build: it could check capture consentless bugreport permission
+ // and approve the report when it's granted.
+ boolean captureConsentlessBugreportOnUserdebugBuildGranted = false;
+ if ((Build.IS_USERDEBUG || Build.IS_ENG)
+ && (flags & IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT) != 0) {
+ AttributionSource attributionSource =
+ new AttributionSource.Builder(callingUid)
+ .setPackageName(callingPackage)
+ .build();
+ captureConsentlessBugreportOnUserdebugBuildGranted =
+ mPermissionManager.checkPermissionForDataDelivery(
+ Manifest.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
+ attributionSource,
+ /* message= */ null)
+ == PERMISSION_GRANTED;
+ }
+ if (captureConsentlessBugreportOnUserdebugBuildGranted) {
+ try {
+ PendingReportRec rec =
+ new PendingReportRec(
+ callingPackage, receiverClass, reportId, flags, listener);
+ Log.d(TAG, "approving consentless report: " + rec.getUri());
+ listener.onReportApproved();
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "authorizeReportImpl listener.onReportApproved RemoteException: ", e);
+ }
+ }
+
// Save the record for when the PermissionController comes back to authorize it.
PendingReportRec rec = null;
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/input/BatteryController.java b/services/core/java/com/android/server/input/BatteryController.java
index 993b4fd..ff9ce6f 100644
--- a/services/core/java/com/android/server/input/BatteryController.java
+++ b/services/core/java/com/android/server/input/BatteryController.java
@@ -234,7 +234,8 @@
}
private boolean isUsiDevice(int deviceId) {
- return processInputDevice(deviceId, false /*defaultValue*/, InputDevice::supportsUsi);
+ return processInputDevice(deviceId, false /*defaultValue*/,
+ (device) -> device.getHostUsiVersion() != null);
}
@Nullable
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index 35434b7..e21895a 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -136,14 +136,14 @@
@ImeVisibilityStateComputer.VisibilityState int state, int reason) {
switch (state) {
case STATE_SHOW_IME:
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// Send to window manager to show IME after IME layout finishes.
mWindowManagerInternal.showImePostLayout(windowToken, statsToken);
break;
case STATE_HIDE_IME:
if (mService.mCurFocusedWindowClient != null) {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// IMMS only knows of focused window, not the actual IME target.
// e.g. it isn't aware of any window that has both
@@ -154,7 +154,7 @@
mWindowManagerInternal.hideIme(windowToken,
mService.mCurFocusedWindowClient.mSelfReportedDisplayId, statsToken);
} else {
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
}
break;
diff --git a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
index 60167b4..da65f27 100644
--- a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
+++ b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
@@ -59,13 +59,16 @@
private static final long TIMEOUT_MS = 10_000;
/** Handler for registering timeouts for live entries. */
- private final Handler mHandler =
- new Handler(Looper.myLooper(), null /* callback */, true /* async */);
+ private final Handler mHandler;
/** Singleton instance of the History. */
@GuardedBy("ImeTrackerService.this")
private final History mHistory = new History();
+ ImeTrackerService(@NonNull Looper looper) {
+ mHandler = new Handler(looper, null /* callback */, true /* async */);
+ }
+
@NonNull
@Override
public synchronized IBinder onRequestShow(int uid, @ImeTracker.Origin int origin,
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 10c16b6..db61e954 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -182,10 +182,10 @@
*/
boolean onImeShowFlags(@NonNull ImeTracker.Token statsToken, int showFlags) {
if (mPolicy.mA11yRequestingNoSoftKeyboard || mPolicy.mImeHiddenByDisplayPolicy) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
return false;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_ACCESSIBILITY);
if ((showFlags & InputMethodManager.SHOW_FORCED) != 0) {
mRequestedShowExplicitly = true;
mShowForced = true;
@@ -206,15 +206,15 @@
if ((hideFlags & InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mRequestedShowExplicitly || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_IMPLICIT);
return false;
}
if (mShowForced && (hideFlags & InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return false;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HIDE_NOT_ALWAYS);
return true;
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index ce3abfd..2ced988 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -89,6 +89,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
+import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.Process;
@@ -1105,7 +1106,7 @@
new SoftInputShowHideHistory();
@NonNull
- private final ImeTrackerService mImeTrackerService = new ImeTrackerService();
+ private final ImeTrackerService mImeTrackerService;
class SettingsObserver extends ContentObserver {
int mUserId;
@@ -1662,6 +1663,8 @@
true /* allowIo */);
thread.start();
mHandler = Handler.createAsync(thread.getLooper(), this);
+ mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
+ ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
// Note: SettingsObserver doesn't register observers in its constructor.
mSettingsObserver = new SettingsObserver(mHandler);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
@@ -2290,7 +2293,7 @@
mCurClient.mSessionRequestedForAccessibility = false;
mCurClient = null;
mCurVirtualDisplayToScreenMatrix = null;
- ImeTracker.forLogging().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.get().onFailed(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
mMenuController.hideInputMethodMenuLocked();
@@ -3276,8 +3279,7 @@
"InputMethodManagerService#showSoftInput");
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken)) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
return false;
}
final long ident = Binder.clearCallingIdentity();
@@ -3378,7 +3380,7 @@
// TODO(b/261565259): to avoid using null, add package name in ClientState
final String packageName = (mCurEditorInfo != null) ? mCurEditorInfo.packageName : null;
final int uid = mCurClient != null ? mCurClient.mUid : -1;
- statsToken = ImeTracker.forLogging().onRequestShow(packageName, uid,
+ statsToken = ImeTracker.get().onRequestShow(packageName, uid,
ImeTracker.ORIGIN_SERVER_START_INPUT, reason);
}
@@ -3387,19 +3389,19 @@
}
if (!mSystemReady) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
return false;
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SYSTEM_READY);
mVisibilityStateComputer.requestImeVisibility(windowToken, true);
// Ensure binding the connection when IME is going to show.
mBindingController.setCurrentMethodVisible();
final IInputMethodInvoker curMethod = getCurMethodLocked();
- ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
if (curMethod != null) {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_HAS_IME);
mCurStatsToken = null;
if (lastClickToolType != MotionEvent.TOOL_TYPE_UNKNOWN) {
@@ -3410,7 +3412,7 @@
mVisibilityStateComputer.setInputShown(true);
return true;
} else {
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = statsToken;
}
return false;
@@ -3426,10 +3428,9 @@
synchronized (ImfLock.class) {
if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken)) {
if (isInputShown()) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
} else {
- ImeTracker.forLogging().onCancelled(statsToken,
+ ImeTracker.get().onCancelled(statsToken,
ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
}
return false;
@@ -3462,7 +3463,7 @@
} else {
uid = -1;
}
- statsToken = ImeTracker.forLogging().onRequestHide(packageName, uid,
+ statsToken = ImeTracker.get().onRequestHide(packageName, uid,
ImeTracker.ORIGIN_SERVER_HIDE_INPUT, reason);
}
@@ -3488,15 +3489,15 @@
// delivered to the IME process as an IPC. Hence the inconsistency between
// IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
// the final state.
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
mVisibilityApplier.performHideIme(windowToken, statsToken, resultReceiver, reason);
} else {
- ImeTracker.forLogging().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
+ ImeTracker.get().onCancelled(statsToken, ImeTracker.PHASE_SERVER_SHOULD_HIDE);
}
mBindingController.setCurrentMethodNotVisible();
mVisibilityStateComputer.clearImeShowFlags();
// Cancel existing statsToken for show IME as we got a hide request.
- ImeTracker.forLogging().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
+ ImeTracker.get().onCancelled(mCurStatsToken, ImeTracker.PHASE_SERVER_WAIT_IME);
mCurStatsToken = null;
return shouldHideSoftInput;
}
@@ -3768,16 +3769,16 @@
// be made before input is started in it.
final ClientState cs = mClients.get(client.asBinder());
if (cs == null) {
- ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
throw new IllegalArgumentException("unknown client " + client.asBinder());
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_KNOWN);
if (!isImeClientFocused(mCurFocusedWindow, cs)) {
Slog.w(TAG, String.format("Ignoring %s of uid %d : %s", methodName, uid, client));
return false;
}
}
- ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
return true;
}
@@ -4554,8 +4555,7 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
synchronized (ImfLock.class) {
if (!calledWithValidTokenLocked(token)) {
- ImeTracker.forLogging().onFailed(statsToken,
- ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ ImeTracker.get().onFailed(statsToken, ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
return;
}
final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(windowToken);
@@ -4616,7 +4616,9 @@
info.requestWindowName, info.imeControlTargetName, info.imeLayerTargetName,
info.imeSurfaceParentName));
- mImeTrackerService.onImmsUpdate(statsToken.mBinder, info.requestWindowName);
+ if (statsToken != null) {
+ mImeTrackerService.onImmsUpdate(statsToken.mBinder, info.requestWindowName);
+ }
}
@BinderThread
@@ -4658,13 +4660,10 @@
}
@VisibleForTesting
- ImeVisibilityStateComputer getVisibilityStateComputer() {
- return mVisibilityStateComputer;
- }
-
- @VisibleForTesting
ImeVisibilityApplier getVisibilityApplier() {
- return mVisibilityApplier;
+ synchronized (ImfLock.class) {
+ return mVisibilityApplier;
+ }
}
@GuardedBy("ImfLock.class")
diff --git a/services/core/java/com/android/server/inputmethod/TEST_MAPPING b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
index 0ccd75d..bd95c5b 100644
--- a/services/core/java/com/android/server/inputmethod/TEST_MAPPING
+++ b/services/core/java/com/android/server/inputmethod/TEST_MAPPING
@@ -2,6 +2,9 @@
"imports": [
{
"path": "frameworks/base/core/java/android/view/inputmethod"
+ },
+ {
+ "path": "frameworks/base/services/tests/InputMethodSystemServerTests"
}
]
}
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 7f6c2d6..8f65775 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -1155,6 +1155,34 @@
return nanoappIds;
}
+ @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
+ /**
+ * Puts the context hub in and out of test mode. Test mode is a clean state
+ * where tests can be executed in the same environment. If enable is true,
+ * this will enable test mode by unloading all nanoapps. If enable is false,
+ * this will disable test mode and reverse the actions of enabling test mode
+ * by loading all preloaded nanoapps. This puts CHRE in a normal state.
+ *
+ * This should only be used for a test environment, either through a
+ * @TestApi or development tools. This should not be used in a production
+ * environment.
+ *
+ * @param enable If true, put the context hub in test mode. If false, disable
+ * test mode.
+ * @return If true, the operation was successful; false otherwise.
+ */
+ @Override
+ public boolean setTestMode(boolean enable) {
+ super.setTestMode_enforcePermission();
+ boolean status = mContextHubWrapper.setTestMode(enable);
+
+ // Query nanoapps to update service state after test mode state change.
+ for (int contextHubId: mDefaultClientMap.keySet()) {
+ queryNanoAppsInternal(contextHubId);
+ }
+ return status;
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 3581b02..ca184ee 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -382,6 +382,23 @@
*/
public abstract void registerExistingCallback(int contextHubId) throws RemoteException;
+ /**
+ * Puts the context hub in and out of test mode. Test mode is a clean state
+ * where tests can be executed in the same environment. If enable is true,
+ * this will enable test mode by unloading all nanoapps. If enable is false,
+ * this will disable test mode and reverse the actions of enabling test mode
+ * by loading all preloaded nanoapps. This puts CHRE in a normal state.
+ *
+ * This should only be used for a test environment, either through a
+ * @TestApi or development tools. This should not be used in a production
+ * environment.
+ *
+ * @param enable If true, put the context hub in test mode. If false, disable
+ * test mode.
+ * @return If true, the operation was successful; false otherwise.
+ */
+ public abstract boolean setTestMode(boolean enable);
+
private static class ContextHubWrapperAidl extends IContextHubWrapper
implements IBinder.DeathRecipient {
private android.hardware.contexthub.IContextHub mHub;
@@ -741,6 +758,22 @@
registerExistingCallback(contextHubId);
}
+ public boolean setTestMode(boolean enable) {
+ android.hardware.contexthub.IContextHub hub = getHub();
+ if (hub == null) {
+ return false;
+ }
+
+ try {
+ hub.setTestMode(enable);
+ return true;
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Exception while setting test mode (enable: "
+ + (enable ? "true" : "false") + "): " + e.getMessage());
+ return false;
+ }
+ }
+
private void onSettingChanged(byte setting, boolean enabled) {
android.hardware.contexthub.IContextHub hub = getHub();
if (hub == null) {
@@ -911,6 +944,10 @@
mHub.registerCallback(contextHubId, callback);
}
+ public boolean setTestMode(boolean enable) {
+ return false;
+ }
+
public boolean supportsBtSettingNotifications() {
return false;
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 434c0d7..de3a7ef 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -533,11 +533,6 @@
if (userId == USER_FRP) {
return null;
}
-
- if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
- key = Settings.Secure.LOCK_PATTERN_ENABLED;
- }
-
return readKeyValue(key, defaultValue, userId);
}
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
index 56390a9..15cfca5 100644
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -274,20 +274,16 @@
}
}
- final long endMillis = SystemClock.elapsedRealtime() + SERVICE_CONNECT_TIMEOUT_MS;
- while (SystemClock.elapsedRealtime() <= endMillis) {
+ final long endMillis = SystemClock.uptimeMillis() + SERVICE_CONNECT_TIMEOUT_MS;
+ do {
final IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
if (binder != null) {
binder.linkToDeath(
() -> Slog.w(TAG, String.format("service '%s' died", IDMAP_SERVICE)), 0);
return binder;
}
-
- try {
- Thread.sleep(SERVICE_CONNECT_INTERVAL_SLEEP_MS);
- } catch (InterruptedException ignored) {
- }
- }
+ SystemClock.sleep(SERVICE_CONNECT_INTERVAL_SLEEP_MS);
+ } while (SystemClock.uptimeMillis() <= endMillis);
throw new TimeoutException(
String.format("Failed to connect to '%s' in %d milliseconds", IDMAP_SERVICE,
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index d252d40..b1c6f8c 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -20,6 +20,7 @@
import static com.android.server.pm.DexOptHelper.useArtService;
import static com.android.server.pm.PackageManagerService.TAG;
+import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import android.annotation.NonNull;
@@ -586,11 +587,14 @@
Slog.wtf(TAG, "Package was null!", new Throwable());
return;
}
- // TODO(b/251903639): Call into ART Service.
- try {
- mArtManagerService.clearAppProfiles(pkg);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ if (useArtService()) {
+ destroyAppProfilesWithArtService(pkg);
+ } else {
+ try {
+ mArtManagerService.clearAppProfiles(pkg);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
}
@@ -629,13 +633,28 @@
}
private void destroyAppProfilesLeafLIF(AndroidPackage pkg) {
- // TODO(b/251903639): Call into ART Service.
- try {
- mInstaller.destroyAppProfiles(pkg.getPackageName());
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- } catch (Installer.InstallerException e) {
- Slog.w(TAG, String.valueOf(e));
+ if (useArtService()) {
+ destroyAppProfilesWithArtService(pkg);
+ } else {
+ try {
+ mInstaller.destroyAppProfiles(pkg.getPackageName());
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ } catch (Installer.InstallerException e) {
+ Slog.w(TAG, String.valueOf(e));
+ }
+ }
+ }
+
+ private void destroyAppProfilesWithArtService(AndroidPackage pkg) {
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ getPackageManagerLocal().withFilteredSnapshot()) {
+ try {
+ DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, pkg.getPackageName());
+ } catch (IllegalArgumentException e) {
+ // Package isn't found, but that should only happen due to race.
+ Slog.w(TAG, e);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 5c4c7c9..faa06f7 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -331,6 +331,7 @@
/** Adds listener for package update */
public void addPackagesUpdatedListener(PackagesUpdatedListener listener)
throws LegacyDexoptDisabledException {
+ // TODO(b/251903639): Evaluate whether this needs to support ART Service or not.
Installer.checkLegacyDexoptDisabled();
synchronized (mLock) {
mPackagesUpdatedListeners.add(listener);
@@ -629,6 +630,8 @@
/** Gets the size of a package. */
private long getPackageSize(@NonNull Computer snapshot, String pkg) {
+ // TODO(b/251903639): Make this in line with the calculation in
+ // `DexOptHelper.DexoptDoneHandler`.
PackageInfo info = snapshot.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
long size = 0;
if (info != null && info.applicationInfo != null) {
@@ -723,6 +726,8 @@
return optimizePackages(pkgs, lowStorageThreshold, updatedPackages, isPostBootUpdate);
} finally {
// Always let the pinner service know about changes.
+ // TODO(b/251903639): ART Service does this for all dexopts, while the code below only
+ // runs for background jobs. We should try to make them behave the same.
notifyPinService(updatedPackages);
// Only notify IORap the primary dex opt, because we don't want to
// invalidate traces unnecessary due to b/161633001 and that it's
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 2752104..094b182 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -766,7 +766,7 @@
*/
crossProfileResults = mCrossProfileIntentResolverEngine.resolveIntent(this, intent,
resolvedType, userId, flags, pkgName, hasNonNegativePriorityResult,
- mSettings::getPackage);
+ resolveForStart, mSettings::getPackage);
if (intent.hasWebURI() || !crossProfileResults.isEmpty()) sortResult = true;
} else {
final PackageStateInternal setting =
@@ -791,7 +791,7 @@
*/
crossProfileResults = mCrossProfileIntentResolverEngine.resolveIntent(this, intent,
resolvedType, userId, flags, pkgName, false,
- mSettings::getPackage);
+ resolveForStart, mSettings::getPackage);
}
/*
@@ -2998,35 +2998,40 @@
}
ipw.println("Dexopt state:");
ipw.increaseIndent();
- Collection<? extends PackageStateInternal> pkgSettings;
- if (setting != null) {
- pkgSettings = Collections.singletonList(setting);
+ if (DexOptHelper.useArtService()) {
+ DexOptHelper.dumpDexoptState(ipw, packageName);
} else {
- pkgSettings = mSettings.getPackages().values();
- }
-
- for (PackageStateInternal pkgSetting : pkgSettings) {
- final AndroidPackage pkg = pkgSetting.getPkg();
- if (pkg == null || pkg.isApex()) {
- // Skip APEX which is not dex-optimized
- continue;
+ Collection<? extends PackageStateInternal> pkgSettings;
+ if (setting != null) {
+ pkgSettings = Collections.singletonList(setting);
+ } else {
+ pkgSettings = mSettings.getPackages().values();
}
- final String pkgName = pkg.getPackageName();
- ipw.println("[" + pkgName + "]");
+
+ for (PackageStateInternal pkgSetting : pkgSettings) {
+ final AndroidPackage pkg = pkgSetting.getPkg();
+ if (pkg == null || pkg.isApex()) {
+ // Skip APEX which is not dex-optimized
+ continue;
+ }
+ final String pkgName = pkg.getPackageName();
+ ipw.println("[" + pkgName + "]");
+ ipw.increaseIndent();
+
+ // TODO(b/251903639): Call into ART Service.
+ try {
+ mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting,
+ mDexManager.getPackageUseInfoOrDefault(pkgName));
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
+ ipw.decreaseIndent();
+ }
+ ipw.println("BgDexopt state:");
ipw.increaseIndent();
-
- // TODO(b/251903639): Call into ART Service.
- try {
- mPackageDexOptimizer.dumpDexoptState(ipw, pkg, pkgSetting,
- mDexManager.getPackageUseInfoOrDefault(pkgName));
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
+ mBackgroundDexOptService.dump(ipw);
ipw.decreaseIndent();
}
- ipw.println("BgDexopt state:");
- ipw.increaseIndent();
- mBackgroundDexOptService.dump(ipw);
ipw.decreaseIndent();
break;
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
index 397fdd8..e149b04 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolverEngine.java
@@ -84,15 +84,16 @@
* @param pkgName the application package name this Intent is limited to.
* @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active
* and valid) ResolveInfo in current profile.
+ * @param resolveForStart true if resolution occurs to start an activity.
* @param pkgSettingFunction function to find PackageStateInternal for given package
* @return list of {@link CrossProfileDomainInfo} from linked profiles.
*/
public List<CrossProfileDomainInfo> resolveIntent(@NonNull Computer computer, Intent intent,
String resolvedType, int userId, long flags, String pkgName,
- boolean hasNonNegativePriorityResult,
+ boolean hasNonNegativePriorityResult, boolean resolveForStart,
Function<String, PackageStateInternal> pkgSettingFunction) {
return resolveIntentInternal(computer, intent, resolvedType, userId, userId, flags, pkgName,
- hasNonNegativePriorityResult, pkgSettingFunction, null);
+ hasNonNegativePriorityResult, resolveForStart, pkgSettingFunction, null);
}
/**
@@ -113,13 +114,14 @@
* @param pkgName the application package name this Intent is limited to.
* @param hasNonNegativePriorityResult signifies if current profile have any non-negative(active
* and valid) ResolveInfo in current profile.
+ * @param resolveForStart true if resolution occurs to start an activity.
* @param pkgSettingFunction function to find PackageStateInternal for given package
* @param visitedUserIds users for which we have already performed resolution
* @return list of {@link CrossProfileDomainInfo} from linked profiles.
*/
private List<CrossProfileDomainInfo> resolveIntentInternal(@NonNull Computer computer,
Intent intent, String resolvedType, int sourceUserId, int userId, long flags,
- String pkgName, boolean hasNonNegativePriorityResult,
+ String pkgName, boolean hasNonNegativePriorityResult, boolean resolveForStart,
Function<String, PackageStateInternal> pkgSettingFunction,
Set<Integer> visitedUserIds) {
@@ -184,7 +186,8 @@
// Choosing strategy based on source and target user
CrossProfileResolver crossProfileResolver =
- chooseCrossProfileResolver(computer, userId, targetUserId);
+ chooseCrossProfileResolver(computer, userId, targetUserId,
+ resolveForStart, flags);
/*
If {@link CrossProfileResolver} is available for source,target pair we will call it to
@@ -217,8 +220,8 @@
if (allowChainedResolution) {
crossProfileDomainInfos.addAll(resolveIntentInternal(computer, intent,
resolvedType, sourceUserId, targetUserId, flags, pkgName,
- hasNonNegativePriority(crossProfileInfos), pkgSettingFunction,
- visitedUserIds));
+ hasNonNegativePriority(crossProfileInfos), resolveForStart,
+ pkgSettingFunction, visitedUserIds));
}
}
@@ -233,18 +236,21 @@
* @param computer {@link Computer} instance used for resolution by {@link ComponentResolverApi}
* @param sourceUserId source user
* @param targetUserId target user
+ * @param resolveForStart true if resolution occurs to start an activity.
+ * @param flags used for intent resolver selection
* @return {@code CrossProfileResolver} which has value if source and target have
* strategy configured otherwise null.
*/
@SuppressWarnings("unused")
private CrossProfileResolver chooseCrossProfileResolver(@NonNull Computer computer,
- @UserIdInt int sourceUserId, @UserIdInt int targetUserId) {
+ @UserIdInt int sourceUserId, @UserIdInt int targetUserId, boolean resolveForStart,
+ long flags) {
/**
* If source or target user is clone profile, using {@link NoFilteringResolver}
* We would return NoFilteringResolver only if it is allowed(feature flag is set).
*/
if (shouldUseNoFilteringResolver(sourceUserId, targetUserId)) {
- if (NoFilteringResolver.isIntentRedirectionAllowed()) {
+ if (NoFilteringResolver.isIntentRedirectionAllowed(mContext, resolveForStart, flags)) {
return new NoFilteringResolver(computer.getComponentResolver(),
mUserManager);
} else {
@@ -384,7 +390,6 @@
ephemeral activities.
*/
candidates = resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates);
-
return new QueryIntentActivitiesResult(computer.applyPostResolutionFilter(candidates,
instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
userId, intent));
@@ -404,11 +409,10 @@
*/
candidates = filterCandidatesWithDomainPreferredActivitiesLPr(computer, intent,
matchFlags, candidates, crossProfileCandidates, userId,
- areWebInstantAppsDisabled, pkgSettingFunction);
+ areWebInstantAppsDisabled, resolveForStart, pkgSettingFunction);
} else {
candidates.addAll(resolveInfoFromCrossProfileDomainInfo(crossProfileCandidates));
}
-
return new QueryIntentActivitiesResult(sortResult, addInstant, candidates);
}
@@ -421,13 +425,14 @@
* @param crossProfileCandidates crossProfileDomainInfos from cross profile, it have ResolveInfo
* @param userId user id of source user
* @param areWebInstantAppsDisabled true if web instant apps are disabled
+ * @param resolveForStart true if intent is for resolution
* @param pkgSettingFunction function to find PackageStateInternal for given package
* @return list of ResolveInfo
*/
private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Computer computer,
Intent intent, long matchFlags, List<ResolveInfo> candidates,
List<CrossProfileDomainInfo> crossProfileCandidates, int userId,
- boolean areWebInstantAppsDisabled,
+ boolean areWebInstantAppsDisabled, boolean resolveForStart,
Function<String, PackageStateInternal> pkgSettingFunction) {
final boolean debug = (intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0;
@@ -439,7 +444,7 @@
final List<ResolveInfo> result =
filterCandidatesWithDomainPreferredActivitiesLPrBody(computer, intent, matchFlags,
candidates, crossProfileCandidates, userId, areWebInstantAppsDisabled,
- debug, pkgSettingFunction);
+ debug, resolveForStart, pkgSettingFunction);
if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
Slog.v(TAG, "Filtered results with preferred activities. New candidates count: "
@@ -461,13 +466,14 @@
* @param userId user id of source user
* @param areWebInstantAppsDisabled true if web instant apps are disabled
* @param debug true if resolution logs needed to be printed
+ * @param resolveForStart true if intent is for resolution
* @param pkgSettingFunction function to find PackageStateInternal for given package
* @return list of resolve infos
*/
private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
Computer computer, Intent intent, long matchFlags, List<ResolveInfo> candidates,
List<CrossProfileDomainInfo> crossProfileCandidates, int userId,
- boolean areWebInstantAppsDisabled, boolean debug,
+ boolean areWebInstantAppsDisabled, boolean debug, boolean resolveForStart,
Function<String, PackageStateInternal> pkgSettingFunction) {
final ArrayList<ResolveInfo> result = new ArrayList<>();
final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
@@ -525,7 +531,7 @@
// calling cross profile strategy to filter corresponding results
result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
- DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE));
+ DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, resolveForStart));
includeBrowser = true;
} else {
Pair<List<ResolveInfo>, Integer> infosAndLevel = mDomainVerificationManager
@@ -539,7 +545,7 @@
// calling cross profile strategy to filter corresponding results
result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
- DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE));
+ DomainVerificationManagerInternal.APPROVAL_LEVEL_NONE, resolveForStart));
} else {
result.addAll(approvedInfos);
@@ -547,7 +553,7 @@
// calling cross profile strategy to filter corresponding results
result.addAll(filterCrossProfileCandidatesWithDomainPreferredActivities(computer,
intent, matchFlags, categorizeResolveInfoByTargetUser, userId,
- highestApproval));
+ highestApproval, resolveForStart));
}
}
@@ -612,11 +618,13 @@
* CrossProfileDomainInfos
* @param sourceUserId user id for intent
* @param highestApprovalLevel domain approval level
+ * @param resolveForStart true if intent is for resolution
* @return list of ResolveInfos
*/
private List<ResolveInfo> filterCrossProfileCandidatesWithDomainPreferredActivities(
Computer computer, Intent intent, long flags, SparseArray<List<CrossProfileDomainInfo>>
- categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel) {
+ categorizeResolveInfoByTargetUser, int sourceUserId, int highestApprovalLevel,
+ boolean resolveForStart) {
List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
@@ -629,7 +637,8 @@
// finding cross profile strategy based on source and target user
CrossProfileResolver crossProfileIntentResolver =
chooseCrossProfileResolver(computer, sourceUserId,
- categorizeResolveInfoByTargetUser.keyAt(index));
+ categorizeResolveInfoByTargetUser.keyAt(index), resolveForStart,
+ flags);
// if strategy is available call it and add its filtered results
if (crossProfileIntentResolver != null) {
crossProfileDomainInfos.addAll(crossProfileIntentResolver
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 53e23e0..de37080 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -23,6 +23,7 @@
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_MAINLINE_UPDATE;
import static com.android.server.pm.PackageManagerService.REASON_BOOT_AFTER_OTA;
import static com.android.server.pm.PackageManagerService.REASON_CMDLINE;
import static com.android.server.pm.PackageManagerService.REASON_FIRST_BOOT;
@@ -32,14 +33,12 @@
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter;
import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_APEX_PKG;
import static com.android.server.pm.PackageManagerServiceUtils.REMOVE_IF_NULL_PKG;
+import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;
import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.Context;
import android.content.Intent;
@@ -52,18 +51,20 @@
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalManagerRegistry;
+import com.android.server.LocalServices;
+import com.android.server.PinnerService;
import com.android.server.art.ArtManagerLocal;
import com.android.server.art.DexUseManagerLocal;
+import com.android.server.art.ReasonMapping;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
@@ -85,10 +86,7 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
-import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
@@ -100,17 +98,9 @@
private final PackageManagerService mPm;
- public boolean isDexOptDialogShown() {
- synchronized (mLock) {
- return mDexOptDialogShown;
- }
- }
-
- // TODO: Is this lock really necessary?
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private boolean mDexOptDialogShown;
+ // Start time for the boot dexopt in performPackageDexOptUpgradeIfNeeded when ART Service is
+ // used, to make it available to the onDexoptDone callback.
+ private volatile long mBootDexoptStartTime;
DexOptHelper(PackageManagerService pm) {
mPm = pm;
@@ -129,7 +119,7 @@
* which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
* and {@code numberOfPackagesFailed}.
*/
- public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates, boolean showDialog,
+ public int[] performDexOptUpgrade(List<PackageStateInternal> packageStates,
final int compilationReason, boolean bootComplete)
throws LegacyDexoptDisabledException {
Installer.checkLegacyDexoptDisabled();
@@ -221,18 +211,6 @@
+ numberOfPackagesToDexopt + ": " + pkg.getPackageName());
}
- if (showDialog) {
- try {
- ActivityManager.getService().showBootMessage(
- mPm.mContext.getResources().getString(R.string.android_upgrading_apk,
- numberOfPackagesVisited, numberOfPackagesToDexopt), true);
- } catch (RemoteException e) {
- }
- synchronized (mLock) {
- mDexOptDialogShown = true;
- }
- }
-
int pkgCompilationReason = compilationReason;
if (useProfileForDexopt) {
// Use background dexopt mode to try and use the profile. Note that this does not
@@ -240,6 +218,7 @@
pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT;
}
+ // TODO(b/251903639): Do this when ART Service is used, or remove it from here.
if (SystemProperties.getBoolean(mPm.PRECOMPILE_LAYOUTS, false)) {
mPm.mArtManagerService.compileLayouts(packageState, pkg);
}
@@ -290,7 +269,7 @@
* Checks if system UI package (typically "com.android.systemui") needs to be re-compiled, and
* compiles it if needed.
*/
- private void checkAndDexOptSystemUi() throws LegacyDexoptDisabledException {
+ private void checkAndDexOptSystemUi(int reason) throws LegacyDexoptDisabledException {
Installer.checkLegacyDexoptDisabled();
Computer snapshot = mPm.snapshotComputer();
String sysUiPackageName =
@@ -301,10 +280,6 @@
return;
}
- // It could also be after mainline update, but we're not introducing a new reason just for
- // this special case.
- int reason = REASON_BOOT_AFTER_OTA;
-
String defaultCompilerFilter = getCompilerFilterForReason(reason);
String targetCompilerFilter =
SystemProperties.get("dalvik.vm.systemuicompilerfilter", defaultCompilerFilter);
@@ -347,49 +322,68 @@
compilerFilter, null /* splitName */, dexoptFlags));
}
- @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
- public void performPackageDexOptUpgradeIfNeeded() throws LegacyDexoptDisabledException {
+ /**
+ * Called during startup to do any boot time dexopting. This can occasionally be time consuming
+ * (30+ seconds) and the function will block until it is complete.
+ */
+ public void performPackageDexOptUpgradeIfNeeded() {
PackageManagerServiceUtils.enforceSystemOrRoot(
"Only the system can request package update");
- // The default is "true".
- if (!"false".equals(DeviceConfig.getProperty("runtime", "dexopt_system_ui_on_boot"))) {
- // System UI is important to user experience, so we check it after a mainline update or
- // an OTA. It may need to be re-compiled in these cases.
- if (hasBcpApexesChanged() || mPm.isDeviceUpgrading()) {
- checkAndDexOptSystemUi();
- }
- }
-
- // We need to re-extract after an OTA.
- boolean causeUpgrade = mPm.isDeviceUpgrading();
-
- // First boot or factory reset.
- // Note: we also handle devices that are upgrading to N right now as if it is their
- // first boot, as they do not have profile data.
- boolean causeFirstBoot = mPm.isFirstBoot() || mPm.isPreNUpgrade();
-
- if (!causeUpgrade && !causeFirstBoot) {
+ int reason;
+ if (mPm.isFirstBoot()) {
+ reason = REASON_FIRST_BOOT; // First boot or factory reset.
+ } else if (mPm.isDeviceUpgrading()) {
+ reason = REASON_BOOT_AFTER_OTA;
+ } else if (hasBcpApexesChanged()) {
+ reason = REASON_BOOT_AFTER_MAINLINE_UPDATE;
+ } else {
return;
}
- final Computer snapshot = mPm.snapshotComputer();
- List<PackageStateInternal> pkgSettings =
- getPackagesForDexopt(snapshot.getPackageStates().values(), mPm);
-
final long startTime = System.nanoTime();
- final int[] stats = performDexOptUpgrade(pkgSettings, mPm.isPreNUpgrade() /* showDialog */,
- causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT_AFTER_OTA,
- false /* bootComplete */);
+ if (useArtService()) {
+ mBootDexoptStartTime = startTime;
+ getArtManagerLocal().onBoot(DexoptOptions.convertToArtServiceDexoptReason(reason),
+ null /* progressCallbackExecutor */, null /* progressCallback */);
+ } else {
+ try {
+ // System UI is important to user experience, so we check it after a mainline update
+ // or an OTA. It may need to be re-compiled in these cases.
+ checkAndDexOptSystemUi(reason);
+
+ if (reason != REASON_BOOT_AFTER_OTA && reason != REASON_FIRST_BOOT) {
+ return;
+ }
+
+ final Computer snapshot = mPm.snapshotComputer();
+
+ // TODO(b/251903639): Align this with how ART Service selects packages for boot
+ // compilation.
+ List<PackageStateInternal> pkgSettings =
+ getPackagesForDexopt(snapshot.getPackageStates().values(), mPm);
+
+ final int[] stats =
+ performDexOptUpgrade(pkgSettings, reason, false /* bootComplete */);
+ reportBootDexopt(startTime, stats[0], stats[1], stats[2]);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void reportBootDexopt(long startTime, int numDexopted, int numSkipped, int numFailed) {
final int elapsedTimeSeconds =
(int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);
final Computer newSnapshot = mPm.snapshotComputer();
- MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_dexopted", stats[0]);
- MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_skipped", stats[1]);
- MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_failed", stats[2]);
+ MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_dexopted", numDexopted);
+ MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_skipped", numSkipped);
+ MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_failed", numFailed);
+ // TODO(b/251903639): getOptimizablePackages calls PackageDexOptimizer.canOptimizePackage
+ // which duplicates logic in ART Service (com.android.server.art.Utils.canDexoptPackage).
MetricsLogger.histogram(mPm.mContext, "opt_dialog_num_total",
getOptimizablePackages(newSnapshot).size());
MetricsLogger.histogram(mPm.mContext, "opt_dialog_time_s", elapsedTimeSeconds);
@@ -421,9 +415,8 @@
@DexOptResult int dexoptStatus;
if (options.isDexoptOnlySecondaryDex()) {
- Optional<Integer> artSrvRes = performDexOptWithArtService(options, 0 /* extraFlags */);
- if (artSrvRes.isPresent()) {
- dexoptStatus = artSrvRes.get();
+ if (useArtService()) {
+ dexoptStatus = performDexOptWithArtService(options, 0 /* extraFlags */);
} else {
try {
return mPm.getDexManager().dexoptSecondaryDex(options);
@@ -463,10 +456,8 @@
// if the package can now be considered up to date for the given filter.
@DexOptResult
private int performDexOptInternal(DexoptOptions options) {
- Optional<Integer> artSrvRes =
- performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
- if (artSrvRes.isPresent()) {
- return artSrvRes.get();
+ if (useArtService()) {
+ return performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
}
AndroidPackage p;
@@ -496,46 +487,26 @@
}
/**
- * Performs dexopt on the given package using ART Service.
- *
- * @return a {@link DexOptResult}, or empty if the request isn't supported so that it is
- * necessary to fall back to the legacy code paths.
+ * Performs dexopt on the given package using ART Service. May only be called when ART Service
+ * is enabled, i.e. when {@link useArtService} returns true.
*/
- private Optional<Integer> performDexOptWithArtService(DexoptOptions options,
+ @DexOptResult
+ private int performDexOptWithArtService(DexoptOptions options,
/*@DexoptFlags*/ int extraFlags) {
- ArtManagerLocal artManager = getArtManagerLocal();
- if (artManager == null) {
- return Optional.empty();
- }
-
try (PackageManagerLocal.FilteredSnapshot snapshot =
getPackageManagerLocal().withFilteredSnapshot()) {
PackageState ops = snapshot.getPackageState(options.getPackageName());
if (ops == null) {
- return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED);
+ return PackageDexOptimizer.DEX_OPT_FAILED;
}
AndroidPackage oap = ops.getAndroidPackage();
if (oap == null) {
- return Optional.of(PackageDexOptimizer.DEX_OPT_FAILED);
+ return PackageDexOptimizer.DEX_OPT_FAILED;
}
- if (oap.isApex()) {
- return Optional.of(PackageDexOptimizer.DEX_OPT_SKIPPED);
- }
-
DexoptParams params = options.convertToDexoptParams(extraFlags);
- if (params == null) {
- return Optional.empty();
- }
-
- DexoptResult result;
- try {
- result = artManager.dexoptPackage(snapshot, options.getPackageName(), params);
- } catch (UnsupportedOperationException e) {
- reportArtManagerFallback(options.getPackageName(), e.toString());
- return Optional.empty();
- }
-
- return Optional.of(convertToDexOptResult(result));
+ DexoptResult result =
+ getArtManagerLocal().dexoptPackage(snapshot, options.getPackageName(), params);
+ return convertToDexOptResult(result);
}
}
@@ -613,14 +584,12 @@
getDefaultCompilerFilter(), null /* splitName */,
DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE);
- // performDexOptWithArtService ignores the snapshot and takes its own, so it can race with
- // the package checks above, but at worst the effect is only a bit less friendly error
- // below.
- Optional<Integer> artSrvRes =
- performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
- int res;
- if (artSrvRes.isPresent()) {
- res = artSrvRes.get();
+ @DexOptResult int res;
+ if (useArtService()) {
+ // performDexOptWithArtService ignores the snapshot and takes its own, so it can race
+ // with the package checks above, but at worst the effect is only a bit less friendly
+ // error below.
+ res = performDexOptWithArtService(options, ArtFlags.FLAG_SHOULD_INCLUDE_DEPENDENCIES);
} else {
try {
res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);
@@ -879,6 +848,26 @@
}
/**
+ * Dumps the dexopt state for the given package, or all packages if it is null.
+ */
+ public static void dumpDexoptState(
+ @NonNull IndentingPrintWriter ipw, @Nullable String packageName) {
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ getPackageManagerLocal().withFilteredSnapshot()) {
+ if (packageName != null) {
+ try {
+ DexOptHelper.getArtManagerLocal().dumpPackage(ipw, snapshot, packageName);
+ } catch (IllegalArgumentException e) {
+ // Package isn't found, but that should only happen due to race.
+ ipw.println(e);
+ }
+ } else {
+ DexOptHelper.getArtManagerLocal().dump(ipw, snapshot);
+ }
+ }
+ }
+
+ /**
* Returns the module names of the APEXes that contribute to bootclasspath.
*/
private static List<String> getBcpApexes() {
@@ -916,23 +905,6 @@
return false;
}
- private @NonNull PackageManagerLocal getPackageManagerLocal() {
- try {
- return LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal.class);
- } catch (ManagerNotFoundException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Called whenever we need to fall back from ART Service to the legacy dexopt code.
- */
- public static void reportArtManagerFallback(String packageName, String reason) {
- // STOPSHIP(b/251903639): Minimize these calls to avoid platform getting shipped with code
- // paths that will always bypass ART Service.
- Slog.i(TAG, "Falling back to old PackageManager dexopt for " + packageName + ": " + reason);
- }
-
/**
* Returns true if ART Service should be used for package optimization.
*/
@@ -954,16 +926,39 @@
}
}
- private static class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
- @NonNull private final PackageManagerService mPm;
-
- DexoptDoneHandler(@NonNull PackageManagerService pm) { mPm = pm; }
-
+ private class DexoptDoneHandler implements ArtManagerLocal.DexoptDoneCallback {
/**
- * Called after every package dexopt operation done by {@link ArtManagerLocal}.
+ * Called after every package dexopt operation done by {@link ArtManagerLocal} (when ART
+ * Service is in use).
*/
@Override
public void onDexoptDone(@NonNull DexoptResult result) {
+ switch (result.getReason()) {
+ case ReasonMapping.REASON_FIRST_BOOT:
+ case ReasonMapping.REASON_BOOT_AFTER_OTA:
+ case ReasonMapping.REASON_BOOT_AFTER_MAINLINE_UPDATE:
+ int numDexopted = 0;
+ int numSkipped = 0;
+ int numFailed = 0;
+ for (DexoptResult.PackageDexoptResult pkgRes :
+ result.getPackageDexoptResults()) {
+ switch (pkgRes.getStatus()) {
+ case DexoptResult.DEXOPT_PERFORMED:
+ numDexopted += 1;
+ break;
+ case DexoptResult.DEXOPT_SKIPPED:
+ numSkipped += 1;
+ break;
+ case DexoptResult.DEXOPT_FAILED:
+ numFailed += 1;
+ break;
+ }
+ }
+
+ reportBootDexopt(mBootDexoptStartTime, numDexopted, numSkipped, numFailed);
+ break;
+ }
+
for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
CompilerStats.PackageStats stats =
mPm.getOrCreateCompilerPackageStats(pkgRes.getPackageName());
@@ -978,6 +973,35 @@
mPm.getPackageUsage().maybeWriteAsync(mPm.mSettings.getPackagesLocked());
mPm.mCompilerStats.maybeWriteAsync();
}
+
+ if (result.getReason().equals(ReasonMapping.REASON_INACTIVE)) {
+ for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
+ if (pkgRes.getStatus() == DexoptResult.DEXOPT_PERFORMED) {
+ long pkgSizeBytes = 0;
+ long pkgSizeBeforeBytes = 0;
+ for (DexoptResult.DexContainerFileDexoptResult dexRes :
+ pkgRes.getDexContainerFileDexoptResults()) {
+ long dexContainerSize = new File(dexRes.getDexContainerFile()).length();
+ pkgSizeBytes += dexRes.getSizeBytes() + dexContainerSize;
+ pkgSizeBeforeBytes += dexRes.getSizeBeforeBytes() + dexContainerSize;
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.APP_DOWNGRADED,
+ pkgRes.getPackageName(), pkgSizeBeforeBytes, pkgSizeBytes,
+ false /* aggressive */);
+ }
+ }
+ }
+
+ var updatedPackages = new ArraySet<String>();
+ for (DexoptResult.PackageDexoptResult pkgRes : result.getPackageDexoptResults()) {
+ if (pkgRes.hasUpdatedArtifacts()) {
+ updatedPackages.add(pkgRes.getPackageName());
+ }
+ }
+ if (!updatedPackages.isEmpty()) {
+ LocalServices.getService(PinnerService.class)
+ .update(updatedPackages, false /* force */);
+ }
}
}
@@ -991,22 +1015,17 @@
}
ArtManagerLocal artManager = new ArtManagerLocal(systemContext);
- // There doesn't appear to be any checks that @NonNull is heeded, so use requireNonNull
- // below to ensure we don't store away a null that we'll fail on later.
- artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */,
- Runnable::run, new DexoptDoneHandler(Objects.requireNonNull(pm)));
+ artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */, Runnable::run,
+ pm.getDexOptHelper().new DexoptDoneHandler());
LocalManagerRegistry.addManager(ArtManagerLocal.class, artManager);
artManager.scheduleBackgroundDexoptJob();
}
/**
- * Returns {@link ArtManagerLocal} if ART Service should be used for package dexopt.
+ * Returns the registered {@link ArtManagerLocal} instance, or else throws an unchecked error.
*/
- private static @Nullable ArtManagerLocal getArtManagerLocal() {
- if (!useArtService()) {
- return null;
- }
+ public static @NonNull ArtManagerLocal getArtManagerLocal() {
try {
return LocalManagerRegistry.getManagerOrThrow(ArtManagerLocal.class);
} catch (ManagerNotFoundException e) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index f0f23cd..a4c9baa 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -158,6 +158,8 @@
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
+import com.android.server.LocalManagerRegistry;
+import com.android.server.art.model.DexoptParams;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.DexManager;
@@ -388,7 +390,8 @@
}
if (reconciledPkg.mCollectedSharedLibraryInfos != null
- || (oldPkgSetting != null && oldPkgSetting.getUsesLibraries() != null)) {
+ || (oldPkgSetting != null
+ && !oldPkgSetting.getSharedLibraryDependencies().isEmpty())) {
// Reconcile if the new package or the old package uses shared libraries.
// It is possible that the old package uses shared libraries but the new one doesn't.
mSharedLibraries.executeSharedLibrariesUpdate(pkg, pkgSetting, null, null,
@@ -1080,19 +1083,32 @@
"MinInstallableTargetSdk__min_installable_target_sdk",
0);
+ // Determine if enforcement is in strict mode
+ boolean strictMode = false;
+ if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__install_block_strict_mode_enabled",
+ false)) {
+ if (parsedPackage.getTargetSdkVersion()
+ < DeviceConfig.getInt(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__strict_mode_target_sdk",
+ 0)) {
+ strictMode = true;
+ }
+ }
+
// Skip enforcement when the bypass flag is set
boolean bypassLowTargetSdkBlock =
((installFlags & PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK) != 0);
// Skip enforcement for tests that were installed from adb
- if (!bypassLowTargetSdkBlock
+ if (!strictMode && !bypassLowTargetSdkBlock
&& ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {
bypassLowTargetSdkBlock = true;
}
// Skip enforcement if the installer package name is not set
// (e.g. "pm install" from shell)
- if (!bypassLowTargetSdkBlock) {
+ if (!strictMode && !bypassLowTargetSdkBlock) {
if (request.getInstallerPackageName() == null) {
bypassLowTargetSdkBlock = true;
} else {
@@ -2325,7 +2341,6 @@
@GuardedBy("mPm.mInstallLock")
private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
- final ArrayList<String> apkPaths = new ArrayList<>();
for (ReconciledPackage reconciledPkg : reconciledPackages) {
final InstallRequest installRequest = reconciledPkg.mInstallRequest;
final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0);
@@ -2344,13 +2359,6 @@
incrementalStorages.add(storage);
}
- // Enabling fs-verity is a blocking operation. To reduce the impact to the install time,
- // collect the files to later enable in a background thread.
- apkPaths.add(pkg.getBaseApkPath());
- if (pkg.getSplitCodePaths() != null) {
- Collections.addAll(apkPaths, pkg.getSplitCodePaths());
- }
-
// Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
if (installRequest.isClearCodeCache()) {
@@ -2392,6 +2400,7 @@
|| installRequest.getInstallReason() == INSTALL_REASON_DEVICE_SETUP;
final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE
+ | DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES
| DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE
| (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);
DexoptOptions dexoptOptions =
@@ -2452,13 +2461,25 @@
realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
- // TODO(b/251903639): Call into ART Service.
- try {
- mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
- null /* instructionSets */, mPm.getOrCreateCompilerPackageStats(pkg),
- mDexManager.getPackageUseInfoOrDefault(packageName), dexoptOptions);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ if (useArtService()) {
+ PackageManagerLocal packageManagerLocal =
+ LocalManagerRegistry.getManager(PackageManagerLocal.class);
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ packageManagerLocal.withFilteredSnapshot()) {
+ DexoptParams params =
+ dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
+ DexOptHelper.getArtManagerLocal().dexoptPackage(
+ snapshot, packageName, params);
+ }
+ } else {
+ try {
+ mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,
+ null /* instructionSets */,
+ mPm.getOrCreateCompilerPackageStats(pkg),
+ mDexManager.getPackageUseInfoOrDefault(packageName), dexoptOptions);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -2479,20 +2500,6 @@
}
PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental(
incrementalStorages);
-
- mInjector.getBackgroundHandler().post(() -> {
- for (String path : apkPaths) {
- if (!VerityUtils.hasFsverity(path)) {
- try {
- VerityUtils.setUpFsverity(path);
- } catch (IOException e) {
- // There's nothing we can do if the setup failed. Since fs-verity is
- // optional, just ignore the error for now.
- Slog.e(TAG, "Failed to fully enable fs-verity to " + path);
- }
- }
- }
- });
}
Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index 492f915..999706a 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -16,7 +16,10 @@
package com.android.server.pm;
+import android.Manifest;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.provider.DeviceConfig;
@@ -47,13 +50,19 @@
/**
* Returns true if intent redirection for clone profile feature flag is set
- * @return value of flag allow_intent_redirection_for_clone_profile
+ * and if its query, then check if calling user have necessary permission
+ * (android.permission.QUERY_CLONED_APPS) as well as required flag
+ * (PackageManager.MATCH_CLONE_PROFILE) bit set.
+ * @return true if resolver would be used for cross profile resolution.
*/
- public static boolean isIntentRedirectionAllowed() {
+ public static boolean isIntentRedirectionAllowed(Context context,
+ boolean resolveForStart, long flags) {
final long token = Binder.clearCallingIdentity();
try {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_APP_CLONING,
- FLAG_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, false /* defaultValue */);
+ FLAG_ALLOW_INTENT_REDIRECTION_FOR_CLONE_PROFILE, false /* defaultValue */)
+ && (resolveForStart || (((flags & PackageManager.MATCH_CLONE_PROFILE) != 0)
+ && hasPermission(context, Manifest.permission.QUERY_CLONED_APPS)));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -123,4 +132,15 @@
// no filtering
return crossProfileDomainInfos;
}
+
+ /**
+ * Checks if calling uid have the mentioned permission
+ * @param context calling context
+ * @param permission permission name
+ * @return true if uid have the permission
+ */
+ private static boolean hasPermission(Context context, String permission) {
+ return context.checkCallingOrSelfPermission(permission)
+ == PackageManager.PERMISSION_GRANTED;
+ }
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 490b2a9..767c0a7 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -168,13 +168,7 @@
Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: "
+ DexOptHelper.packagesToString(others));
for (PackageStateInternal pkg : others) {
- // TODO(b/251903639): Call into ART Service.
- try {
- mPackageManagerService.deleteOatArtifactsOfPackage(
- snapshot, pkg.getPackageName());
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
+ mPackageManagerService.deleteOatArtifactsOfPackage(snapshot, pkg.getPackageName());
}
}
long spaceAvailableNow = getAvailableSpace();
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index 99fff72..4e75210 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -47,7 +47,6 @@
import android.util.ArraySet;
import android.util.SparseArray;
-import com.android.server.pm.Installer.LegacyDexoptDisabledException;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
@@ -708,12 +707,7 @@
@Override
@Deprecated
public final long deleteOatArtifactsOfPackage(String packageName) {
- // TODO(b/251903639): Call into ART Service.
- try {
- return mService.deleteOatArtifactsOfPackage(snapshot(), packageName);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
+ return mService.deleteOatArtifactsOfPackage(snapshot(), packageName);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dfd305a..94e96b0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -196,6 +196,7 @@
import com.android.server.Watchdog;
import com.android.server.apphibernation.AppHibernationManagerInternal;
import com.android.server.art.DexUseManagerLocal;
+import com.android.server.art.model.DeleteResult;
import com.android.server.compat.CompatChange;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.Installer.InstallerException;
@@ -552,6 +553,7 @@
private static final int REQUIRED_VERIFIERS_MAX_COUNT = 2;
// Compilation reasons.
+ // TODO(b/260124949): Clean this up with the legacy dexopt code.
public static final int REASON_FIRST_BOOT = 0;
public static final int REASON_BOOT_AFTER_OTA = 1;
public static final int REASON_POST_BOOT = 2;
@@ -565,7 +567,8 @@
public static final int REASON_AB_OTA = 10;
public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 11;
public static final int REASON_CMDLINE = 12;
- public static final int REASON_SHARED = 13;
+ public static final int REASON_BOOT_AFTER_MAINLINE_UPDATE = 13;
+ public static final int REASON_SHARED = 14;
public static final int REASON_LAST = REASON_SHARED;
@@ -588,7 +591,6 @@
private final int mDefParseFlags;
private final String[] mSeparateProcesses;
private final boolean mIsUpgrade;
- private final boolean mIsPreNUpgrade;
private final boolean mIsPreNMR1Upgrade;
private final boolean mIsPreQUpgrade;
@@ -1734,7 +1736,6 @@
mInstantAppResolverConnection = testParams.instantAppResolverConnection;
mInstantAppResolverSettingsComponent = testParams.instantAppResolverSettingsComponent;
mIsPreNMR1Upgrade = testParams.isPreNmr1Upgrade;
- mIsPreNUpgrade = testParams.isPreNupgrade;
mIsPreQUpgrade = testParams.isPreQupgrade;
mIsUpgrade = testParams.isUpgrade;
mMetrics = testParams.Metrics;
@@ -2069,10 +2070,6 @@
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
- // When upgrading from pre-N, we need to handle package extraction like first boot,
- // as there is no profiling data available.
- mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
-
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
@@ -2953,16 +2950,6 @@
}
}
if (doTrim) {
- if (!isFirstBoot()) {
- if (mDexOptHelper.isDexOptDialogShown()) {
- try {
- ActivityManager.getService().showBootMessage(
- mContext.getResources().getString(
- R.string.android_upgrading_fstrim), true);
- } catch (RemoteException e) {
- }
- }
- }
sm.runMaintenance();
}
} else {
@@ -2974,12 +2961,7 @@
}
public void updatePackagesIfNeeded() {
- // TODO(b/251903639): Call into ART Service.
- try {
- mDexOptHelper.performPackageDexOptUpgradeIfNeeded();
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
+ mDexOptHelper.performPackageDexOptUpgradeIfNeeded();
}
private void notifyPackageUseInternal(String packageName, int reason) {
@@ -2997,6 +2979,10 @@
return mDexManager;
}
+ /*package*/ DexOptHelper getDexOptHelper() {
+ return mDexOptHelper;
+ }
+
/*package*/ DynamicCodeLogger getDynamicCodeLogger() {
return mDynamicCodeLogger;
}
@@ -4827,35 +4813,6 @@
}
@Override
- public void dumpProfiles(String packageName, boolean dumpClassesAndMethods) {
- /* Only the shell, root, or the app user should be able to dump profiles. */
- final int callingUid = Binder.getCallingUid();
- final Computer snapshot = snapshotComputer();
- final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
- if (callingUid != Process.SHELL_UID
- && callingUid != Process.ROOT_UID
- && !ArrayUtils.contains(callerPackageNames, packageName)) {
- throw new SecurityException("dumpProfiles");
- }
-
- AndroidPackage pkg = snapshot.getPackage(packageName);
- if (pkg == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
- }
-
- // TODO(b/251903639): Call into ART Service.
- synchronized (mInstallLock) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
- try {
- mArtManagerService.dumpProfiles(pkg, dumpClassesAndMethods);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
- @Override
public void enterSafeMode() {
PackageManagerServiceUtils.enforceSystemOrRoot(
"Only the system can request entering safe mode");
@@ -5464,9 +5421,11 @@
String loadingPkgDexCodeIsa = InstructionSets.getDexCodeInstructionSet(
VMRuntime.getInstructionSet(loadingPkgAbi));
if (!loaderIsa.equals(loadingPkgDexCodeIsa)) {
- // TODO(b/251903639): Make this crash to surface this problem
- // better.
- Slog.w(PackageManagerService.TAG,
+ // TODO(b/251903639): We make this a wtf to surface any situations
+ // where this argument doesn't correspond to our expectations. Later
+ // it should be turned into an IllegalArgumentException, when we can
+ // assume it's the caller that's wrong rather than us.
+ Log.wtf(TAG,
"Invalid loaderIsa in notifyDexLoad call from "
+ loadingPackageName + ", uid " + callingUid
+ ": expected " + loadingPkgDexCodeIsa + ", got "
@@ -5541,33 +5500,6 @@
return new ParceledListSlice<>(result);
}
- /**
- * Reconcile the information we have about the secondary dex files belonging to
- * {@code packageName} and the actual dex files. For all dex files that were
- * deleted, update the internal records and delete the generated oat files.
- */
- @Override
- public void reconcileSecondaryDexFiles(String packageName) {
- if (useArtService()) {
- // ART Service currently relies on a GC to find stale oat files, including secondary
- // dex files. Hence it doesn't use this call for anything.
- return;
- }
-
- final Computer snapshot = snapshotComputer();
- if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) {
- return;
- } else if (snapshot.isInstantAppInternal(
- packageName, UserHandle.getCallingUserId(), Process.SYSTEM_UID)) {
- return;
- }
- try {
- mDexManager.reconcileSecondaryDexFiles(packageName);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
- }
-
@Override
public void registerDexModule(String packageName, String dexModulePath,
boolean isSharedModule,
@@ -6663,6 +6595,47 @@
}
}
+ /** @deprecated For legacy shell command only. */
+ @Override
+ @Deprecated
+ public void legacyDumpProfiles(String packageName, boolean dumpClassesAndMethods)
+ throws LegacyDexoptDisabledException {
+ /* Only the shell, root, or the app user should be able to dump profiles. */
+ final int callingUid = Binder.getCallingUid();
+ final Computer snapshot = snapshotComputer();
+ final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
+ if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID
+ && !ArrayUtils.contains(callerPackageNames, packageName)) {
+ throw new SecurityException("dumpProfiles");
+ }
+
+ AndroidPackage pkg = snapshot.getPackage(packageName);
+ if (pkg == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+
+ synchronized (mInstallLock) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
+ mArtManagerService.dumpProfiles(pkg, dumpClassesAndMethods);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ /** @deprecated For legacy shell command only. */
+ @Override
+ @Deprecated
+ public void legacyReconcileSecondaryDexFiles(String packageName)
+ throws LegacyDexoptDisabledException {
+ final Computer snapshot = snapshotComputer();
+ if (snapshot.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ return;
+ } else if (snapshot.isInstantAppInternal(
+ packageName, UserHandle.getCallingUserId(), Process.SYSTEM_UID)) {
+ return;
+ }
+ mDexManager.reconcileSecondaryDexFiles(packageName);
+ }
+
@Override
@SuppressWarnings("GuardedBy")
public void updateRuntimePermissionsFingerprint(@UserIdInt int userId) {
@@ -7112,17 +7085,39 @@
return AndroidPackageUtils.canHaveOatDir(packageState, packageState.getPkg());
}
- long deleteOatArtifactsOfPackage(@NonNull Computer snapshot, String packageName)
- throws LegacyDexoptDisabledException {
+ long deleteOatArtifactsOfPackage(@NonNull Computer snapshot, String packageName) {
PackageManagerServiceUtils.enforceSystemOrRootOrShell(
"Only the system or shell can delete oat artifacts");
- PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
- if (packageState == null || packageState.getPkg() == null) {
- return -1; // error code of deleteOptimizedFiles
+ if (DexOptHelper.useArtService()) {
+ // TODO(chiuwinson): Retrieve filtered snapshot from Computer instance instead.
+ try (PackageManagerLocal.FilteredSnapshot filteredSnapshot =
+ PackageManagerServiceUtils.getPackageManagerLocal()
+ .withFilteredSnapshot()) {
+ try {
+ DeleteResult res = DexOptHelper.getArtManagerLocal().deleteDexoptArtifacts(
+ filteredSnapshot, packageName);
+ return res.getFreedBytes();
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, e.toString());
+ return -1;
+ } catch (IllegalStateException e) {
+ Slog.wtfStack(TAG, e.toString());
+ return -1;
+ }
+ }
+ } else {
+ PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
+ if (packageState == null || packageState.getPkg() == null) {
+ return -1; // error code of deleteOptimizedFiles
+ }
+ try {
+ return mDexManager.deleteOptimizedFiles(
+ ArtUtils.createArtPackageInfo(packageState.getPkg(), packageState));
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
- return mDexManager.deleteOptimizedFiles(
- ArtUtils.createArtPackageInfo(packageState.getPkg(), packageState));
}
List<String> getMimeGroupInternal(@NonNull Computer snapshot, String packageName,
@@ -7491,10 +7486,6 @@
return mPlatformPackage;
}
- boolean isPreNUpgrade() {
- return mIsPreNUpgrade;
- }
-
boolean isPreNMR1Upgrade() {
return mIsPreNMR1Upgrade;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 7c1f054..e2ddba5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -41,6 +41,7 @@
"ab-ota",
"inactive",
"cmdline",
+ "boot-after-mainline-update",
// "shared" must be the last entry
"shared"
};
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index 08ff51d..e5cfa67 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -63,7 +63,6 @@
public InstantAppResolverConnection instantAppResolverConnection;
public ComponentName instantAppResolverSettingsComponent;
public boolean isPreNmr1Upgrade;
- public boolean isPreNupgrade;
public boolean isPreQupgrade;
public boolean isUpgrade;
public LegacyPermissionManagerInternal legacyPermissionManagerInternal;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 0de1a4e..ad8e35d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -24,6 +24,7 @@
import static android.system.OsConstants.O_RDWR;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
@@ -91,6 +92,7 @@
import com.android.internal.util.HexDump;
import com.android.server.EventLogTags;
import com.android.server.IntentResolver;
+import com.android.server.LocalManagerRegistry;
import com.android.server.Watchdog;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.PackageDexUsage;
@@ -201,6 +203,17 @@
private static final boolean FORCE_PACKAGE_PARSED_CACHE_ENABLED = false;
/**
+ * Returns the registered PackageManagerLocal instance, or else throws an unchecked error.
+ */
+ public static @NonNull PackageManagerLocal getPackageManagerLocal() {
+ try {
+ return LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal.class);
+ } catch (ManagerNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Checks if the package was inactive during since <code>thresholdTimeinMillis</code>.
* Package is considered active, if:
* 1) It was active in foreground.
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 0685435..4263791 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -179,6 +179,7 @@
"cancel-bg-dexopt-job", "delete-dexopt", "dump-profiles", "snapshot-profile", "art");
final IPackageManager mInterface;
+ private final PackageManagerInternal mPm;
final LegacyPermissionManagerInternal mLegacyPermissionManager;
final PermissionManager mPermissionManager;
final Context mContext;
@@ -195,6 +196,7 @@
PackageManagerShellCommand(@NonNull IPackageManager packageManager,
@NonNull Context context, @NonNull DomainVerificationShell domainVerificationShell) {
mInterface = packageManager;
+ mPm = LocalServices.getService(PackageManagerInternal.class);
mLegacyPermissionManager = LocalServices.getService(LegacyPermissionManagerInternal.class);
mPermissionManager = context.getSystemService(PermissionManager.class);
mContext = context;
@@ -1968,9 +1970,10 @@
}
}
- private int runreconcileSecondaryDexFiles() throws RemoteException {
+ private int runreconcileSecondaryDexFiles()
+ throws RemoteException, LegacyDexoptDisabledException {
String packageName = getNextArg();
- mInterface.reconcileSecondaryDexFiles(packageName);
+ mPm.legacyReconcileSecondaryDexFiles(packageName);
return 0;
}
@@ -1979,63 +1982,53 @@
return 0;
}
- private int runBgDexOpt() throws RemoteException {
- // TODO(b/251903639): Call into ART Service.
- try {
- String opt = getNextOption();
+ private int runBgDexOpt() throws RemoteException, LegacyDexoptDisabledException {
+ String opt = getNextOption();
- if (opt == null) {
- List<String> packageNames = new ArrayList<>();
- String arg;
- while ((arg = getNextArg()) != null) {
- packageNames.add(arg);
- }
- if (!BackgroundDexOptService.getService().runBackgroundDexoptJob(
- packageNames.isEmpty() ? null : packageNames)) {
- getOutPrintWriter().println("Failure");
- return -1;
- }
- } else {
- String extraArg = getNextArg();
- if (extraArg != null) {
- getErrPrintWriter().println("Invalid argument: " + extraArg);
- return -1;
- }
-
- switch (opt) {
- case "--cancel":
- return cancelBgDexOptJob();
-
- case "--disable":
- BackgroundDexOptService.getService().setDisableJobSchedulerJobs(true);
- break;
-
- case "--enable":
- BackgroundDexOptService.getService().setDisableJobSchedulerJobs(false);
- break;
-
- default:
- getErrPrintWriter().println("Unknown option: " + opt);
- return -1;
- }
+ if (opt == null) {
+ List<String> packageNames = new ArrayList<>();
+ String arg;
+ while ((arg = getNextArg()) != null) {
+ packageNames.add(arg);
+ }
+ if (!BackgroundDexOptService.getService().runBackgroundDexoptJob(
+ packageNames.isEmpty() ? null : packageNames)) {
+ getOutPrintWriter().println("Failure");
+ return -1;
+ }
+ } else {
+ String extraArg = getNextArg();
+ if (extraArg != null) {
+ getErrPrintWriter().println("Invalid argument: " + extraArg);
+ return -1;
}
- getOutPrintWriter().println("Success");
- return 0;
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ switch (opt) {
+ case "--cancel":
+ return cancelBgDexOptJob();
+
+ case "--disable":
+ BackgroundDexOptService.getService().setDisableJobSchedulerJobs(true);
+ break;
+
+ case "--enable":
+ BackgroundDexOptService.getService().setDisableJobSchedulerJobs(false);
+ break;
+
+ default:
+ getErrPrintWriter().println("Unknown option: " + opt);
+ return -1;
+ }
}
+
+ getOutPrintWriter().println("Success");
+ return 0;
}
- private int cancelBgDexOptJob() throws RemoteException {
- // TODO(b/251903639): Call into ART Service.
- try {
- BackgroundDexOptService.getService().cancelBackgroundDexoptJob();
- getOutPrintWriter().println("Success");
- return 0;
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- }
+ private int cancelBgDexOptJob() throws RemoteException, LegacyDexoptDisabledException {
+ BackgroundDexOptService.getService().cancelBackgroundDexoptJob();
+ getOutPrintWriter().println("Success");
+ return 0;
}
private int runDeleteDexOpt() throws RemoteException {
@@ -2045,8 +2038,7 @@
pw.println("Error: no package name");
return 1;
}
- long freedBytes = LocalServices.getService(PackageManagerInternal.class)
- .deleteOatArtifactsOfPackage(packageName);
+ long freedBytes = mPm.deleteOatArtifactsOfPackage(packageName);
if (freedBytes < 0) {
pw.println("Error: delete failed");
return 1;
@@ -2056,7 +2048,7 @@
return 0;
}
- private int runDumpProfiles() throws RemoteException {
+ private int runDumpProfiles() throws RemoteException, LegacyDexoptDisabledException {
final PrintWriter pw = getOutPrintWriter();
boolean dumpClassesAndMethods = false;
@@ -2073,7 +2065,7 @@
}
String packageName = getNextArg();
- mInterface.dumpProfiles(packageName, dumpClassesAndMethods);
+ mPm.legacyDumpProfiles(packageName, dumpClassesAndMethods);
return 0;
}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 53fdfaa..2a1172c 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -1219,7 +1219,7 @@
@NonNull
@Override
- public List<SharedLibrary> getUsesLibraries() {
+ public List<SharedLibrary> getSharedLibraryDependencies() {
return (List<SharedLibrary>) (List<?>) pkgState.getUsesLibraryInfos();
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index e5aaddb..10673c6 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -422,15 +422,18 @@
if (instructionSets == null) {
throw new IllegalStateException("instructionSet == null");
}
- String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
- for (String codePath : allCodePaths) {
- for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- // TODO(b/251903639): Call into ART Service.
- try {
- mPm.mInstaller.rmdex(codePath, dexCodeInstructionSet);
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
- } catch (Installer.InstallerException ignored) {
+ // TODO(b/265813358): ART Service currently doesn't support deleting optimized artifacts
+ // relative to an arbitrary APK path. Skip this and rely on its file GC instead.
+ if (!DexOptHelper.useArtService()) {
+ String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ for (String codePath : allCodePaths) {
+ for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+ try {
+ mPm.mInstaller.rmdex(codePath, dexCodeInstructionSet);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ } catch (Installer.InstallerException ignored) {
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 920fafd..165e476 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2694,10 +2694,15 @@
FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-1, -1);
- try {
- FileUtils.copy(mSettingsFilename, mSettingsReserveCopyFilename);
+ try (FileInputStream in = new FileInputStream(mSettingsFilename);
+ FileOutputStream out = new FileOutputStream(mSettingsReserveCopyFilename)) {
+ FileUtils.copy(in, out);
+ out.flush();
+ FileUtils.sync(out);
} catch (IOException e) {
- Slog.e(TAG, "Failed to backup settings", e);
+ Slog.e(TAG,
+ "Failed to write reserve copy of settings: " + mSettingsReserveCopyFilename,
+ e);
}
try {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 53a5648..3340e12 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -35,6 +35,7 @@
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.KeyguardManager;
@@ -1480,36 +1481,45 @@
@Override
public void setUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("set user admin");
-
+ final long sessionId = logGrantAdminJourneyBegin(userId);
+ UserInfo info;
synchronized (mPackagesLock) {
- UserInfo info;
synchronized (mUsersLock) {
info = getUserInfoLU(userId);
}
if (info == null || info.isAdmin()) {
// Exit if no user found with that id, or the user is already an Admin.
+ logUserJourneyError(sessionId,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
+ userId);
return;
}
-
info.flags ^= UserInfo.FLAG_ADMIN;
writeUserLP(getUserDataLU(info.id));
}
+ logGrantAdminJourneyFinish(sessionId, userId, info.userType, info.flags);
}
@Override
public void revokeUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("revoke admin privileges");
+ final long sessionId = logRevokeAdminJourneyBegin(userId);
+ UserData user;
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
- UserData user = getUserDataLU(userId);
+ user = getUserDataLU(userId);
if (user == null || !user.info.isAdmin()) {
// Exit if no user found with that id, or the user is not an Admin.
+ logUserJourneyError(sessionId, FrameworkStatsLog
+ .USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
+ userId);
return;
}
user.info.flags ^= UserInfo.FLAG_ADMIN;
writeUserLP(user);
}
}
+ logRevokeAdminJourneyFinish(sessionId, userId, user.info.userType, user.info.flags);
}
/**
@@ -2924,7 +2934,13 @@
final Intent broadcast = new Intent(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mContext.sendBroadcastAsUser(broadcast, UserHandle.of(userId));
+ // Setting the MOST_RECENT policy allows us to discard older broadcasts
+ // still waiting to be delivered.
+ final Bundle options = BroadcastOptions.makeBasic()
+ .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+ .toBundle();
+ mContext.sendBroadcastAsUser(broadcast, UserHandle.of(userId),
+ null /* receiverPermission */, options);
}
});
}
@@ -3718,14 +3734,12 @@
}
if (userVersion < 6) {
- final boolean splitSystemUser = UserManager.isSplitSystemUser();
synchronized (mUsersLock) {
for (int i = 0; i < mUsers.size(); i++) {
UserData userData = mUsers.valueAt(i);
- // In non-split mode, only user 0 can have restricted profiles
- if (!splitSystemUser && userData.info.isRestricted()
- && (userData.info.restrictedProfileParentId
- == UserInfo.NO_PROFILE_GROUP_ID)) {
+ // Only system user can have restricted profiles
+ if (userData.info.isRestricted() && (userData.info.restrictedProfileParentId
+ == UserInfo.NO_PROFILE_GROUP_ID)) {
userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
userIdsToWrite.add(userData.info.id);
}
@@ -5142,12 +5156,38 @@
userId, userType, flags, finish);
}
+ private long logGrantAdminJourneyBegin(@UserIdInt int userId) {
+ return logUserJourneyBegin(
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
+ userId);
+ }
+
+ private void logGrantAdminJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
+ @UserInfoFlag int flags) {
+ logUserJourneyFinish(sessionId,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
+ userId, userType, flags, true);
+ }
+
+ private long logRevokeAdminJourneyBegin(@UserIdInt int userId) {
+ return logUserJourneyBegin(
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
+ userId);
+ }
+
+ private void logRevokeAdminJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
+ @UserInfoFlag int flags) {
+ logUserJourneyFinish(sessionId,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
+ userId, userType, flags, true);
+ }
+
private void logUserJourneyFinish(long sessionId, int journey, @UserIdInt int userId,
String userType, @UserInfoFlag int flags, boolean finish) {
// log the journey atom with the user metadata
FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId,
- journey, /* origin_user= */ -1, userId,
+ journey, /* origin_user= */ getCurrentUserId(), userId,
UserManager.getUserTypeForStatsd(userType), flags);
int event;
@@ -5158,6 +5198,12 @@
case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE:
event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER;
break;
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
+ break;
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
+ break;
default:
throw new IllegalArgumentException("Journey " + journey + " not expected.");
}
@@ -5179,6 +5225,12 @@
case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE:
event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER;
break;
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
+ break;
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
+ break;
default:
throw new IllegalArgumentException("Journey " + journey + " not expected.");
}
@@ -5188,6 +5240,27 @@
return sessionId;
}
+ private void logUserJourneyError(long sessionId, int journey, @UserIdInt int userId) {
+
+ // log the journey atom with the user metadata
+ FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId,
+ journey, /* origin_user= */ getCurrentUserId(), userId);
+
+ int event;
+ switch (journey) {
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
+ break;
+ case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
+ event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
+ break;
+ default:
+ throw new IllegalArgumentException("Journey " + journey + " not expected.");
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
+ event, FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__ERROR);
+ }
+
/** Register callbacks for statsd pulled atoms. */
private void registerStatsCallbacks() {
final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
@@ -6496,7 +6569,6 @@
pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
com.android.internal.R.bool.config_guestUserEphemeral));
pw.println(" Force ephemeral users: " + mForceEphemeralUsers);
- pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
final boolean isHeadlessSystemUserMode = isHeadlessSystemUserMode();
pw.println(" Is headless-system mode: " + isHeadlessSystemUserMode);
if (isHeadlessSystemUserMode != RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
diff --git a/services/core/java/com/android/server/pm/UserVisibilityMediator.java b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
index 66d390f..1f935f90 100644
--- a/services/core/java/com/android/server/pm/UserVisibilityMediator.java
+++ b/services/core/java/com/android/server/pm/UserVisibilityMediator.java
@@ -36,6 +36,7 @@
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.DebugUtils;
import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
@@ -80,6 +81,7 @@
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
+ private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
public static final int SECONDARY_DISPLAY_MAPPING_FAILED = -1;
@@ -88,7 +90,7 @@
* Whether a user / display assignment requires adding an entry to the
* {@code mUsersOnSecondaryDisplays} map.
*/
- @IntDef(flag = false, prefix = {"SECONDARY_DISPLAY_MAPPING_"}, value = {
+ @IntDef(flag = false, prefix = {PREFIX_SECONDARY_DISPLAY_MAPPING}, value = {
SECONDARY_DISPLAY_MAPPING_NEEDED,
SECONDARY_DISPLAY_MAPPING_NOT_NEEDED,
SECONDARY_DISPLAY_MAPPING_FAILED
@@ -102,6 +104,7 @@
private final Object mLock = new Object();
private final boolean mVisibleBackgroundUsersEnabled;
+ private final boolean mVisibleBackgroundUserOnDefaultDisplayAllowed;
@UserIdInt
@GuardedBy("mLock")
@@ -110,7 +113,7 @@
/**
* Map of background users started visible on displays (key is user id, value is display id).
*
- * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
+ * <p>Only set when {@code mVisibleBackgroundUsersEnabled} is {@code true}.
*/
@Nullable
@GuardedBy("mLock")
@@ -121,7 +124,7 @@
* {@link #assignUserToExtraDisplay(int, int)}) displays assigned to user (key is display id,
* value is user id).
*
- * <p>Only set when {@code mUsersOnSecondaryDisplaysEnabled} is {@code true}.
+ * <p>Only set when {@code mVisibleBackgroundUsersEnabled} is {@code true}.
*/
@Nullable
@GuardedBy("mLock")
@@ -143,12 +146,17 @@
new CopyOnWriteArrayList<>();
UserVisibilityMediator(Handler handler) {
- this(UserManager.isVisibleBackgroundUsersEnabled(), handler);
+ this(UserManager.isVisibleBackgroundUsersEnabled(),
+ // TODO(b/261538232): get visibleBackgroundUserOnDefaultDisplayAllowed from UM
+ /* visibleBackgroundUserOnDefaultDisplayAllowed= */ false, handler);
}
@VisibleForTesting
- UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled, Handler handler) {
+ UserVisibilityMediator(boolean backgroundUsersOnDisplaysEnabled,
+ boolean visibleBackgroundUserOnDefaultDisplayAllowed, Handler handler) {
mVisibleBackgroundUsersEnabled = backgroundUsersOnDisplaysEnabled;
+ mVisibleBackgroundUserOnDefaultDisplayAllowed =
+ visibleBackgroundUserOnDefaultDisplayAllowed;
if (mVisibleBackgroundUsersEnabled) {
mUsersAssignedToDisplayOnStart = new SparseIntArray();
mExtraDisplaysAssignedToUsers = new SparseIntArray();
@@ -203,7 +211,12 @@
return result;
}
- int mappingResult = canAssignUserToDisplayLocked(userId, profileGroupId, displayId);
+ int mappingResult = canAssignUserToDisplayLocked(userId, profileGroupId, userStartMode,
+ displayId);
+ if (DBG) {
+ Slogf.d(TAG, "mapping result: %s",
+ secondaryDisplayMappingStatusToString(mappingResult));
+ }
if (mappingResult == SECONDARY_DISPLAY_MAPPING_FAILED) {
return USER_ASSIGNMENT_RESULT_FAILURE;
}
@@ -263,14 +276,16 @@
+ "(it should be BACKGROUND_USER_VISIBLE", userId, displayId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
- if (userStartMode == USER_START_MODE_BACKGROUND_VISIBLE
- && displayId == DEFAULT_DISPLAY && !isProfile(userId, profileGroupId)) {
+
+ boolean visibleBackground = userStartMode == USER_START_MODE_BACKGROUND_VISIBLE;
+ if (displayId == DEFAULT_DISPLAY && visibleBackground
+ && !mVisibleBackgroundUserOnDefaultDisplayAllowed
+ && !isProfile(userId, profileGroupId)) {
Slogf.wtf(TAG, "cannot start full user (%d) visible on default display", userId);
return USER_ASSIGNMENT_RESULT_FAILURE;
}
boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
-
if (displayId != DEFAULT_DISPLAY) {
if (foreground) {
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
@@ -309,26 +324,47 @@
}
return foreground || displayId != DEFAULT_DISPLAY
- ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
- : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
+ || (visibleBackground && mVisibleBackgroundUserOnDefaultDisplayAllowed)
+ ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
+ : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
}
@GuardedBy("mLock")
@SecondaryDisplayMappingStatus
private int canAssignUserToDisplayLocked(@UserIdInt int userId,
- @UserIdInt int profileGroupId, int displayId) {
- if (displayId == DEFAULT_DISPLAY
- && (!mVisibleBackgroundUsersEnabled || !isProfile(userId, profileGroupId))) {
- // Don't need to do anything because methods (such as isUserVisible()) already
- // know that the current user (and its profiles) is assigned to the default display.
- // But on MUMD devices, profiles are only supported in the default display, so it
- // cannot return yet as it needs to check if the parent is also assigned to the
- // DEFAULT_DISPLAY (this is done indirectly below when it checks that the profile parent
- // is the current user, as the current user is always assigned to the DEFAULT_DISPLAY).
- if (DBG) {
- Slogf.d(TAG, "ignoring mapping for default display");
+ @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
+ if (displayId == DEFAULT_DISPLAY) {
+ boolean mappingNeeded = false;
+ if (mVisibleBackgroundUserOnDefaultDisplayAllowed
+ && userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
+ int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
+ if (userStartedOnDefaultDisplay != USER_NULL) {
+ Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
+ + " default display because user %d already did so", userId,
+ userStartedOnDefaultDisplay);
+ return SECONDARY_DISPLAY_MAPPING_FAILED;
+ }
+ mappingNeeded = true;
}
- return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
+ if (!mappingNeeded && mVisibleBackgroundUsersEnabled
+ && isProfile(userId, profileGroupId)) {
+ mappingNeeded = true;
+ }
+
+ if (!mappingNeeded) {
+ // Don't need to do anything because methods (such as isUserVisible()) already
+ // know that the current user (and its profiles) is assigned to the default display.
+ // But on MUMD devices, profiles are only supported in the default display, so it
+ // cannot return yet as it needs to check if the parent is also assigned to the
+ // DEFAULT_DISPLAY (this is done indirectly below when it checks that the profile
+ // parent is the current user, as the current user is always assigned to the
+ // DEFAULT_DISPLAY).
+ if (DBG) {
+ Slogf.d(TAG, "ignoring mapping for default display for user %d starting as %s",
+ userId, userStartModeToString(userStartMode));
+ }
+ return SECONDARY_DISPLAY_MAPPING_NOT_NEEDED;
+ }
}
if (userId == UserHandle.USER_SYSTEM) {
@@ -421,13 +457,14 @@
return false;
}
- int userAssignedToDisplay = getUserAssignedToDisplay(displayId,
- /* returnCurrentUserByDefault= */ false);
+ // First check if the user started on display
+ int userAssignedToDisplay = getUserStartedOnDisplay(displayId);
if (userAssignedToDisplay != USER_NULL) {
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because display was assigned"
+ " to user %d on start", userId, displayId, userAssignedToDisplay);
return false;
}
+ // Then if was assigned extra
userAssignedToDisplay = mExtraDisplaysAssignedToUsers.get(userId, USER_NULL);
if (userAssignedToDisplay != USER_NULL) {
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user %d was already "
@@ -435,7 +472,8 @@
return false;
}
if (DBG) {
- Slogf.d(TAG, "addding %d -> %d to map", displayId, userId);
+ Slogf.d(TAG, "addding %d -> %d to mExtraDisplaysAssignedToUsers", displayId,
+ userId);
}
mExtraDisplaysAssignedToUsers.put(displayId, userId);
}
@@ -501,7 +539,7 @@
mStartedProfileGroupIds.delete(userId);
if (!mVisibleBackgroundUsersEnabled) {
- // Don't need to do update mUsersOnSecondaryDisplays because methods (such as
+ // Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
// isUserVisible()) already know that the current user (and their profiles) is
// assigned to the default display.
return;
@@ -536,11 +574,10 @@
return true;
}
- // Device doesn't support multiple users on multiple displays, so only users checked above
- // can be visible
if (!mVisibleBackgroundUsersEnabled) {
if (DBG) {
- Slogf.d(TAG, "isUserVisible(%d): false for non-current user on MUMD", userId);
+ Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
+ + " device doesn't support visible background users", userId);
}
return false;
}
@@ -559,15 +596,29 @@
* See {@link UserManagerInternal#isUserVisible(int, int)}.
*/
public boolean isUserVisible(@UserIdInt int userId, int displayId) {
- if (displayId == Display.INVALID_DISPLAY) {
+ if (displayId == INVALID_DISPLAY) {
return false;
}
- if (!mVisibleBackgroundUsersEnabled || displayId == Display.DEFAULT_DISPLAY) {
- // TODO(b/245939659): will need to move the displayId == Display.DEFAULT_DISPLAY outside
- // once it supports background users on DEFAULT_DISPLAY (for example, passengers in a
- // no-driver configuration)
- return isCurrentUserOrRunningProfileOfCurrentUser(userId);
+ // Current user is always visible on:
+ // - Default display
+ // - Secondary displays when device doesn't support visible bg users
+ // - Or when explicitly added (which is checked below)
+ if (isCurrentUserOrRunningProfileOfCurrentUser(userId)
+ && (displayId == DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
+ if (VERBOSE) {
+ Slogf.v(TAG, "isUserVisible(%d, %d): returning true for current user/profile",
+ userId, displayId);
+ }
+ return true;
+ }
+
+ if (!mVisibleBackgroundUsersEnabled) {
+ if (DBG) {
+ Slogf.d(TAG, "isUserVisible(%d, %d): returning false as device does not support"
+ + " visible background users", userId, displayId);
+ }
+ return false;
}
synchronized (mLock) {
@@ -575,7 +626,8 @@
// User assigned to display on start
return true;
}
- // Check for extra assignment
+
+ // Check for extra display assignment
return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
}
}
@@ -585,15 +637,31 @@
*/
public int getDisplayAssignedToUser(@UserIdInt int userId) {
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
- return Display.DEFAULT_DISPLAY;
+ if (mVisibleBackgroundUserOnDefaultDisplayAllowed) {
+ // When device supports visible bg users on default display, the default display is
+ // assigned to the current user, unless a user is started visible on it
+ int userStartedOnDefaultDisplay;
+ synchronized (mLock) {
+ userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
+ }
+ if (userStartedOnDefaultDisplay != USER_NULL) {
+ if (DBG) {
+ Slogf.d(TAG, "getDisplayAssignedToUser(%d): returning INVALID_DISPLAY for "
+ + "current user user %d was started on DEFAULT_DISPLAY",
+ userId, userStartedOnDefaultDisplay);
+ }
+ return INVALID_DISPLAY;
+ }
+ }
+ return DEFAULT_DISPLAY;
}
if (!mVisibleBackgroundUsersEnabled) {
- return Display.INVALID_DISPLAY;
+ return INVALID_DISPLAY;
}
synchronized (mLock) {
- return mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY);
+ return mUsersAssignedToDisplayOnStart.get(userId, INVALID_DISPLAY);
}
}
@@ -605,13 +673,21 @@
}
/**
+ * Gets the user explicitly assigned to a display.
+ */
+ private @UserIdInt int getUserStartedOnDisplay(@UserIdInt int displayId) {
+ return getUserAssignedToDisplay(displayId, /* returnCurrentUserByDefault= */ false);
+ }
+
+ /**
* Gets the user explicitly assigned to a display, or the current user when no user is assigned
* to it (and {@code returnCurrentUserByDefault} is {@code true}).
*/
private @UserIdInt int getUserAssignedToDisplay(@UserIdInt int displayId,
boolean returnCurrentUserByDefault) {
if (returnCurrentUserByDefault
- && (displayId == Display.DEFAULT_DISPLAY || !mVisibleBackgroundUsersEnabled)) {
+ && ((displayId == DEFAULT_DISPLAY && !mVisibleBackgroundUserOnDefaultDisplayAllowed
+ || !mVisibleBackgroundUsersEnabled))) {
return getCurrentUserId();
}
@@ -763,8 +839,10 @@
ipw.print("Supports visible background users on displays: ");
ipw.println(mVisibleBackgroundUsersEnabled);
- dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
+ ipw.print("Allows visible background users on default display: ");
+ ipw.println(mVisibleBackgroundUserOnDefaultDisplayAllowed);
+ dumpSparseIntArray(ipw, mUsersAssignedToDisplayOnStart, "user / display", "u", "d");
dumpSparseIntArray(ipw, mExtraDisplaysAssignedToUsers, "extra display / user",
"d", "u");
@@ -872,4 +950,10 @@
return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
}
}
+
+ private static String secondaryDisplayMappingStatusToString(
+ @SecondaryDisplayMappingStatus int status) {
+ return DebugUtils.constantToString(UserVisibilityMediator.class,
+ PREFIX_SECONDARY_DISPLAY_MAPPING, status);
+ }
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index b5b6347..d8b6cd5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -50,11 +50,15 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
+import com.android.server.art.ArtManagerLocal;
+import com.android.server.pm.DexOptHelper;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
+import com.android.server.pm.PackageManagerLocal;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageManagerServiceCompilerMapping;
+import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
@@ -210,20 +214,15 @@
Slog.d(TAG, "Requested snapshot for " + packageName + ":" + codePath);
}
- // TODO(b/251903639): Call into ART Service.
- try {
- if (bootImageProfile) {
- snapshotBootImageProfile(callback);
- } else {
- snapshotAppProfile(packageName, codePath, callback);
- }
- } catch (LegacyDexoptDisabledException e) {
- throw new RuntimeException(e);
+ if (bootImageProfile) {
+ snapshotBootImageProfile(callback);
+ } else {
+ snapshotAppProfile(packageName, codePath, callback);
}
}
- private void snapshotAppProfile(String packageName, String codePath,
- ISnapshotRuntimeProfileCallback callback) throws LegacyDexoptDisabledException {
+ private void snapshotAppProfile(
+ String packageName, String codePath, ISnapshotRuntimeProfileCallback callback) {
PackageInfo info = null;
try {
// Note that we use the default user 0 to retrieve the package info.
@@ -260,17 +259,45 @@
}
// All good, create the profile snapshot.
- int appId = UserHandle.getAppId(info.applicationInfo.uid);
- if (appId < 0) {
- postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
- Slog.wtf(TAG, "AppId is -1 for package: " + packageName);
- return;
- }
+ if (DexOptHelper.useArtService()) {
+ ParcelFileDescriptor fd;
- createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath,
- appId, callback);
- // Destroy the snapshot, we no longer need it.
- destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName));
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ PackageManagerServiceUtils.getPackageManagerLocal()
+ .withFilteredSnapshot()) {
+ fd = DexOptHelper.getArtManagerLocal().snapshotAppProfile(
+ snapshot, packageName, splitName);
+ } catch (IllegalArgumentException e) {
+ // ArtManagerLocal.snapshotAppProfile couldn't find the package or split. Since
+ // we've checked them above this can only happen due to race, i.e. the package got
+ // removed. So let's report it as SNAPSHOT_FAILED_PACKAGE_NOT_FOUND even if it was
+ // for the split.
+ // TODO(mast): Reuse the same snapshot to avoid this race.
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_PACKAGE_NOT_FOUND);
+ return;
+ } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+
+ postSuccess(packageName, fd, callback);
+ } else {
+ int appId = UserHandle.getAppId(info.applicationInfo.uid);
+ if (appId < 0) {
+ postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ Slog.wtf(TAG, "AppId is -1 for package: " + packageName);
+ return;
+ }
+
+ try {
+ createProfileSnapshot(packageName, ArtManager.getProfileName(splitName), codePath,
+ appId, callback);
+ // Destroy the snapshot, we no longer need it.
+ destroyProfileSnapshot(packageName, ArtManager.getProfileName(splitName));
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
private void createProfileSnapshot(String packageName, String profileName, String classpath,
@@ -340,23 +367,43 @@
}
}
- private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback)
- throws LegacyDexoptDisabledException {
- // Combine the profiles for boot classpath and system server classpath.
- // This avoids having yet another type of profiles and simplifies the processing.
- String classpath = String.join(":", Os.getenv("BOOTCLASSPATH"),
- Os.getenv("SYSTEMSERVERCLASSPATH"));
+ private void snapshotBootImageProfile(ISnapshotRuntimeProfileCallback callback) {
+ if (DexOptHelper.useArtService()) {
+ ParcelFileDescriptor fd;
- final String standaloneSystemServerJars = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
- if (standaloneSystemServerJars != null) {
- classpath = String.join(":", classpath, standaloneSystemServerJars);
+ try (PackageManagerLocal.FilteredSnapshot snapshot =
+ PackageManagerServiceUtils.getPackageManagerLocal()
+ .withFilteredSnapshot()) {
+ fd = DexOptHelper.getArtManagerLocal().snapshotBootImageProfile(snapshot);
+ } catch (IllegalStateException | ArtManagerLocal.SnapshotProfileException e) {
+ postError(callback, BOOT_IMAGE_ANDROID_PACKAGE,
+ ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
+ return;
+ }
+
+ postSuccess(BOOT_IMAGE_ANDROID_PACKAGE, fd, callback);
+ } else {
+ // Combine the profiles for boot classpath and system server classpath.
+ // This avoids having yet another type of profiles and simplifies the processing.
+ String classpath = String.join(
+ ":", Os.getenv("BOOTCLASSPATH"), Os.getenv("SYSTEMSERVERCLASSPATH"));
+
+ final String standaloneSystemServerJars = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
+ if (standaloneSystemServerJars != null) {
+ classpath = String.join(":", classpath, standaloneSystemServerJars);
+ }
+
+ try {
+ // Create the snapshot.
+ createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME,
+ classpath,
+ /*appId*/ -1, callback);
+ // Destroy the snapshot, we no longer need it.
+ destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME);
+ } catch (LegacyDexoptDisabledException e) {
+ throw new RuntimeException(e);
+ }
}
-
- // Create the snapshot.
- createProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME, classpath,
- /*appId*/ -1, callback);
- // Destroy the snapshot, we no longer need it.
- destroyProfileSnapshot(BOOT_IMAGE_ANDROID_PACKAGE, BOOT_IMAGE_PROFILE_NAME);
}
/**
@@ -620,6 +667,7 @@
private static final int TRON_COMPILATION_REASON_CMDLINE = 22;
private static final int TRON_COMPILATION_REASON_PREBUILT = 23;
private static final int TRON_COMPILATION_REASON_VDEX = 24;
+ private static final int TRON_COMPILATION_REASON_BOOT_AFTER_MAINLINE_UPDATE = 25;
// The annotation to add as a suffix to the compilation reason when dexopt was
// performed with dex metadata.
@@ -634,6 +682,8 @@
case "error" : return TRON_COMPILATION_REASON_ERROR;
case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT;
case "boot-after-ota": return TRON_COMPILATION_REASON_BOOT_AFTER_OTA;
+ case "boot-after-mainline-update":
+ return TRON_COMPILATION_REASON_BOOT_AFTER_MAINLINE_UPDATE;
case "post-boot" : return TRON_COMPILATION_REASON_POST_BOOT;
case "install" : return TRON_COMPILATION_REASON_INSTALL;
case "bg-dexopt" : return TRON_COMPILATION_REASON_BG_DEXOPT;
diff --git a/services/core/java/com/android/server/pm/dex/DexoptOptions.java b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
index d3fba7c..310c0e8 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptOptions.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptOptions.java
@@ -20,18 +20,20 @@
import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
+import android.util.Log;
import com.android.server.art.ReasonMapping;
import com.android.server.art.model.ArtFlags;
import com.android.server.art.model.DexoptParams;
-import com.android.server.pm.DexOptHelper;
import com.android.server.pm.PackageManagerService;
/**
* Options used for dexopt invocations.
*/
public final class DexoptOptions {
+ private static final String TAG = "DexoptOptions";
+
// When set, the profiles will be checked for updates before calling dexopt. If
// the apps profiles didn't update in a meaningful way (decided by the compiler), dexopt
// will be skipped.
@@ -87,8 +89,9 @@
// The set of flags for the dexopt options. It's a mix of the DEXOPT_* flags.
private final int mFlags;
- // When not null, dexopt will optimize only the split identified by this name.
- // It only applies for primary apk and it's always null if mOnlySecondaryDex is true.
+ // When not null, dexopt will optimize only the split identified by this APK file name (not
+ // split name). It only applies for primary apk and it's always null if mOnlySecondaryDex is
+ // true.
private final String mSplitName;
// The reason for invoking dexopt (see PackageManagerService.REASON_* constants).
@@ -201,19 +204,68 @@
}
/**
+ * Returns the ART Service reason for the given PackageManagerService reason. Throws unchecked
+ * exceptions for reasons that aren't supported.
+ */
+ public static @NonNull String convertToArtServiceDexoptReason(int pmDexoptReason) {
+ switch (pmDexoptReason) {
+ case PackageManagerService.REASON_FIRST_BOOT:
+ return ReasonMapping.REASON_FIRST_BOOT;
+ case PackageManagerService.REASON_BOOT_AFTER_OTA:
+ return ReasonMapping.REASON_BOOT_AFTER_OTA;
+ case PackageManagerService.REASON_INSTALL:
+ return ReasonMapping.REASON_INSTALL;
+ case PackageManagerService.REASON_INSTALL_FAST:
+ return ReasonMapping.REASON_INSTALL_FAST;
+ case PackageManagerService.REASON_INSTALL_BULK:
+ return ReasonMapping.REASON_INSTALL_BULK;
+ case PackageManagerService.REASON_INSTALL_BULK_SECONDARY:
+ return ReasonMapping.REASON_INSTALL_BULK_SECONDARY;
+ case PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED:
+ return ReasonMapping.REASON_INSTALL_BULK_DOWNGRADED;
+ case PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED:
+ return ReasonMapping.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
+ case PackageManagerService.REASON_BACKGROUND_DEXOPT:
+ return ReasonMapping.REASON_BG_DEXOPT;
+ case PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE:
+ return ReasonMapping.REASON_INACTIVE;
+ case PackageManagerService.REASON_CMDLINE:
+ return ReasonMapping.REASON_CMDLINE;
+ case PackageManagerService.REASON_POST_BOOT:
+ case PackageManagerService.REASON_SHARED:
+ case PackageManagerService.REASON_AB_OTA:
+ // REASON_POST_BOOT isn't supported - that dexopt stage is getting removed.
+ // REASON_SHARED shouldn't go to ART Service - it's only used at lower levels
+ // in PackageDexOptimizer.
+ // TODO(b/251921228): OTA isn't supported, so REASON_AB_OTA shouldn't come this way
+ // either.
+ throw new UnsupportedOperationException(
+ "ART Service unsupported compilation reason " + pmDexoptReason);
+ default:
+ throw new IllegalArgumentException("Invalid compilation reason " + pmDexoptReason);
+ }
+ }
+
+ /**
* Returns an {@link DexoptParams} instance corresponding to this object, for use with
* {@link com.android.server.art.ArtManagerLocal}.
*
* @param extraFlags extra {@link ArtFlags#DexoptFlags} to set in the returned
* {@code DexoptParams} beyond those converted from this object
- * @return null if the settings cannot be accurately represented, and hence the old
- * PackageManager/installd code paths need to be used.
+ * @throws UnsupportedOperationException if the settings cannot be accurately represented.
*/
- public @Nullable DexoptParams convertToDexoptParams(/*@DexoptFlags*/ int extraFlags) {
+ public @NonNull DexoptParams convertToDexoptParams(/*@DexoptFlags*/ int extraFlags) {
if (mSplitName != null) {
- DexOptHelper.reportArtManagerFallback(
- mPackageName, "Request to optimize only split " + mSplitName);
- return null;
+ // ART Service supports dexopting a single split - see ArtFlags.FLAG_FOR_SINGLE_SPLIT.
+ // However using it here requires searching through the splits to find the one matching
+ // the APK file name in mSplitName, and we don't have the AndroidPackage available for
+ // that.
+ //
+ // Hence we throw here instead, under the assumption that no code paths that dexopt
+ // splits need this conversion (e.g. shell commands with the --split argument are
+ // handled by ART Service directly).
+ throw new UnsupportedOperationException(
+ "Request to optimize only split " + mSplitName + " for " + mPackageName);
}
/*@DexoptFlags*/ int flags = extraFlags;
@@ -236,11 +288,11 @@
flags |= ArtFlags.FLAG_SHOULD_DOWNGRADE;
}
if ((mFlags & DEXOPT_INSTALL_WITH_DEX_METADATA_FILE) == 0) {
- // ART Service cannot be instructed to ignore a DM file if present, so not setting this
- // flag is not supported.
- DexOptHelper.reportArtManagerFallback(
- mPackageName, "DEXOPT_INSTALL_WITH_DEX_METADATA_FILE not set");
- return null;
+ // ART Service cannot be instructed to ignore a DM file if present.
+ Log.w(TAG,
+ "DEXOPT_INSTALL_WITH_DEX_METADATA_FILE not set in request to optimise "
+ + mPackageName
+ + " - ART Service will unconditionally use a DM file if present.");
}
/*@PriorityClassApi*/ int priority;
@@ -269,60 +321,7 @@
// - DEXOPT_IDLE_BACKGROUND_JOB: Its only effect is to allow the debug variant dex2oatd to
// be used, but ART Service never uses that (cf. Artd::GetDex2Oat in artd.cc).
- String reason;
- switch (mCompilationReason) {
- case PackageManagerService.REASON_FIRST_BOOT:
- reason = ReasonMapping.REASON_FIRST_BOOT;
- break;
- case PackageManagerService.REASON_BOOT_AFTER_OTA:
- reason = ReasonMapping.REASON_BOOT_AFTER_OTA;
- break;
- case PackageManagerService.REASON_POST_BOOT:
- // This reason will go away with the legacy dexopt code.
- DexOptHelper.reportArtManagerFallback(
- mPackageName, "Unsupported compilation reason REASON_POST_BOOT");
- return null;
- case PackageManagerService.REASON_INSTALL:
- reason = ReasonMapping.REASON_INSTALL;
- break;
- case PackageManagerService.REASON_INSTALL_FAST:
- reason = ReasonMapping.REASON_INSTALL_FAST;
- break;
- case PackageManagerService.REASON_INSTALL_BULK:
- reason = ReasonMapping.REASON_INSTALL_BULK;
- break;
- case PackageManagerService.REASON_INSTALL_BULK_SECONDARY:
- reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY;
- break;
- case PackageManagerService.REASON_INSTALL_BULK_DOWNGRADED:
- reason = ReasonMapping.REASON_INSTALL_BULK_DOWNGRADED;
- break;
- case PackageManagerService.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED:
- reason = ReasonMapping.REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
- break;
- case PackageManagerService.REASON_BACKGROUND_DEXOPT:
- reason = ReasonMapping.REASON_BG_DEXOPT;
- break;
- case PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE:
- reason = ReasonMapping.REASON_INACTIVE;
- break;
- case PackageManagerService.REASON_CMDLINE:
- reason = ReasonMapping.REASON_CMDLINE;
- break;
- case PackageManagerService.REASON_SHARED:
- case PackageManagerService.REASON_AB_OTA:
- // REASON_SHARED shouldn't go into this code path - it's only used at lower levels
- // in PackageDexOptimizer.
- // TODO(b/251921228): OTA isn't supported, so REASON_AB_OTA shouldn't come this way
- // either.
- throw new UnsupportedOperationException(
- "ART Service unsupported compilation reason " + mCompilationReason);
- default:
- throw new IllegalArgumentException(
- "Invalid compilation reason " + mCompilationReason);
- }
-
- return new DexoptParams.Builder(reason, flags)
+ return new DexoptParams.Builder(convertToArtServiceDexoptReason(mCompilationReason), flags)
.setCompilerFilter(mCompilerFilter)
.setPriorityClass(priority)
.build();
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
index a12c9d0..106b149 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -158,10 +158,11 @@
PackageUserState getStateForUser(@NonNull UserHandle user);
/**
- * @see R.styleable#AndroidManifestUsesLibrary
+ * List of shared libraries that this package declares a dependency on. This includes all
+ * types of libraries, system or app provided and Java or native.
*/
@NonNull
- List<SharedLibrary> getUsesLibraries();
+ List<SharedLibrary> getSharedLibraryDependencies();
/** Whether this represents an APEX module. This is different from an APK inside an APEX. */
boolean isApex();
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
index bc6dab4..91a25db3 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -190,7 +190,7 @@
mUsesSdkLibrariesVersionsMajor = pkgState.getUsesSdkLibrariesVersionsMajor();
mUsesStaticLibraries = pkgState.getUsesStaticLibraries();
mUsesStaticLibrariesVersions = pkgState.getUsesStaticLibrariesVersions();
- mUsesLibraries = Collections.unmodifiableList(pkgState.getUsesLibraries());
+ mUsesLibraries = Collections.unmodifiableList(pkgState.getSharedLibraryDependencies());
mUsesLibraryFiles = Collections.unmodifiableList(pkgState.getUsesLibraryFiles());
setBoolean(Booleans.FORCE_QUERYABLE_OVERRIDE, pkgState.isForceQueryableOverride());
setBoolean(Booleans.HIDDEN_UNTIL_INSTALLED, pkgState.isHiddenUntilInstalled());
@@ -693,7 +693,7 @@
}
@DataClass.Generated.Member
- public @NonNull List<SharedLibrary> getUsesLibraries() {
+ public @NonNull List<SharedLibrary> getSharedLibraryDependencies() {
return mUsesLibraries;
}
diff --git a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java b/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java
index 2bd7cf8..a2177e8 100644
--- a/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java
+++ b/services/core/java/com/android/server/pm/split/DefaultSplitAssetLoader.java
@@ -82,7 +82,7 @@
}
AssetManager assets = new AssetManager();
- assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
diff --git a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java b/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java
index ae42e09..1a8c1996 100644
--- a/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java
+++ b/services/core/java/com/android/server/pm/split/SplitAssetDependencyLoader.java
@@ -80,7 +80,7 @@
private static AssetManager createAssetManagerWithAssets(ApkAssets[] apkAssets) {
final AssetManager assets = new AssetManager();
- assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
assets.setApkAssets(apkAssets, false /*invalidateCaches*/);
return assets;
diff --git a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
index 91bb677..7f733ef 100644
--- a/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
+++ b/services/core/java/com/android/server/policy/DeviceStateProviderImpl.java
@@ -27,6 +27,7 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Environment;
+import android.os.PowerManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -80,7 +81,8 @@
* provided.
*/
public final class DeviceStateProviderImpl implements DeviceStateProvider,
- InputManagerInternal.LidSwitchCallback, SensorEventListener {
+ InputManagerInternal.LidSwitchCallback, SensorEventListener,
+ PowerManager.OnThermalStatusChangedListener {
private static final String TAG = "DeviceStateProviderImpl";
private static final boolean DEBUG = false;
@@ -97,6 +99,10 @@
private static final String FLAG_CANCEL_OVERRIDE_REQUESTS = "FLAG_CANCEL_OVERRIDE_REQUESTS";
private static final String FLAG_APP_INACCESSIBLE = "FLAG_APP_INACCESSIBLE";
private static final String FLAG_EMULATED_ONLY = "FLAG_EMULATED_ONLY";
+ private static final String FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
+ "FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP";
+ private static final String FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL =
+ "FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL";
/** Interface that allows reading the device state configuration. */
interface ReadableConfig {
@@ -152,6 +158,13 @@
break;
case FLAG_EMULATED_ONLY:
flags |= DeviceState.FLAG_EMULATED_ONLY;
+ break;
+ case FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP:
+ flags |= DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP;
+ break;
+ case FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL:
+ flags |= DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL;
+ break;
default:
Slog.w(TAG, "Parsed unknown flag with name: "
+ configFlagString);
@@ -194,6 +207,8 @@
private Boolean mIsLidOpen;
@GuardedBy("mLock")
private final Map<Sensor, SensorEvent> mLatestSensorEvent = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private @PowerManager.ThermalStatus int mThermalStatus = PowerManager.THERMAL_STATUS_NONE;
private DeviceStateProviderImpl(@NonNull Context context,
@NonNull List<DeviceState> deviceStates,
@@ -208,6 +223,16 @@
mOrderedStates = orderedStates;
setStateConditions(deviceStates, stateConditions);
+
+ // If any of the device states are thermal sensitive, i.e. it should be disabled when the
+ // device is overheating, then we will update the list of supported states when thermal
+ // status changes.
+ if (hasThermalSensitiveState(deviceStates)) {
+ PowerManager powerManager = context.getSystemService(PowerManager.class);
+ if (powerManager != null) {
+ powerManager.addThermalStatusListener(this);
+ }
+ }
}
private void setStateConditions(@NonNull List<DeviceState> deviceStates,
@@ -347,16 +372,25 @@
/** Notifies the listener that the set of supported device states has changed. */
private void notifySupportedStatesChanged() {
- DeviceState[] supportedStates;
+ List<DeviceState> supportedStates = new ArrayList<>();
+ Listener listener;
synchronized (mLock) {
if (mListener == null) {
return;
}
-
- supportedStates = Arrays.copyOf(mOrderedStates, mOrderedStates.length);
+ listener = mListener;
+ for (DeviceState deviceState : mOrderedStates) {
+ if (isThermalStatusCriticalOrAbove(mThermalStatus)
+ && deviceState.hasFlag(
+ DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL)) {
+ continue;
+ }
+ supportedStates.add(deviceState);
+ }
}
- mListener.onSupportedDeviceStatesChanged(supportedStates);
+ listener.onSupportedDeviceStatesChanged(
+ supportedStates.toArray(new DeviceState[supportedStates.size()]));
}
/** Computes the current device state and notifies the listener of a change, if needed. */
@@ -639,4 +673,43 @@
return new FileInputStream(mFile);
}
}
+
+ @Override
+ public void onThermalStatusChanged(@PowerManager.ThermalStatus int thermalStatus) {
+ int previousThermalStatus;
+ synchronized (mLock) {
+ previousThermalStatus = mThermalStatus;
+ mThermalStatus = thermalStatus;
+ }
+
+ boolean isThermalStatusCriticalOrAbove = isThermalStatusCriticalOrAbove(thermalStatus);
+ boolean isPreviousThermalStatusCriticalOrAbove =
+ isThermalStatusCriticalOrAbove(previousThermalStatus);
+ if (isThermalStatusCriticalOrAbove != isPreviousThermalStatusCriticalOrAbove) {
+ Slog.i(TAG, "Updating supported device states due to thermal status change."
+ + " isThermalStatusCriticalOrAbove: " + isThermalStatusCriticalOrAbove);
+ notifySupportedStatesChanged();
+ }
+ }
+
+ private static boolean isThermalStatusCriticalOrAbove(
+ @PowerManager.ThermalStatus int thermalStatus) {
+ switch (thermalStatus) {
+ case PowerManager.THERMAL_STATUS_CRITICAL:
+ case PowerManager.THERMAL_STATUS_EMERGENCY:
+ case PowerManager.THERMAL_STATUS_SHUTDOWN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean hasThermalSensitiveState(List<DeviceState> deviceStates) {
+ for (DeviceState state : deviceStates) {
+ if (state.hasFlag(DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 983b7f4..fa81540 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -282,8 +282,9 @@
} else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
mItems.add(mAirplaneModeOn);
} else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)) {
- if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserAdmin()) {
+ if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.BUGREPORT_IN_POWER_MENU, 0, mContext.getUserId()) != 0
+ && isCurrentUserAdmin()) {
mItems.add(new BugReportAction());
}
} else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey)) {
@@ -537,7 +538,7 @@
private boolean isCurrentUserAdmin() {
UserInfo currentUser = getCurrentUser();
- return currentUser == null || currentUser.isAdmin();
+ return currentUser != null && currentUser.isAdmin();
}
private void addUsersToMenu(ArrayList<Action> items) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b7a801a..60751e6 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -575,6 +575,9 @@
// What we do when the user double-taps on home
private int mDoubleTapOnHomeBehavior;
+ // Whether to lock the device after the next app transition has finished.
+ private boolean mLockAfterAppTransitionFinished;
+
// Allowed theater mode wake actions
private boolean mAllowTheaterModeWakeFromKey;
private boolean mAllowTheaterModeWakeFromPowerKey;
@@ -717,7 +720,7 @@
handleRingerChordGesture();
break;
case MSG_SCREENSHOT_CHORD:
- handleScreenShot(msg.arg1, msg.arg2);
+ handleScreenShot(msg.arg1);
break;
}
}
@@ -1073,11 +1076,10 @@
return;
}
- // Make sure the device locks. Unfortunately, this has the side-effect of briefly revealing
- // the lock screen before the dream appears. Note that locking is a side-effect of the no
- // dream action that is executed if we early return above.
- // TODO(b/261662912): Find a better way to lock the device that doesn't result in jank.
- lockNow(null);
+ synchronized (mLock) {
+ // Lock the device after the dream transition has finished.
+ mLockAfterAppTransitionFinished = true;
+ }
dreamManagerInternal.requestDream();
}
@@ -1518,9 +1520,9 @@
|| mShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
}
- private void interceptScreenshotChord(int type, int source, long pressDelay) {
+ private void interceptScreenshotChord(int source, long pressDelay) {
mHandler.removeMessages(MSG_SCREENSHOT_CHORD);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCREENSHOT_CHORD, type, source),
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SCREENSHOT_CHORD, source),
pressDelay);
}
@@ -1590,9 +1592,8 @@
}
};
- private void handleScreenShot(@WindowManager.ScreenshotType int type,
- @WindowManager.ScreenshotSource int source) {
- mDefaultDisplayPolicy.takeScreenshot(type, source);
+ private void handleScreenShot(@WindowManager.ScreenshotSource int source) {
+ mDefaultDisplayPolicy.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, source);
}
@Override
@@ -2197,6 +2198,22 @@
handleTransitionForKeyguardLw(
keyguardGoingAwayCancelled /* startKeyguardExitAnimation */,
true /* notifyOccluded */);
+
+ synchronized (mLock) {
+ mLockAfterAppTransitionFinished = false;
+ }
+ }
+
+ @Override
+ public void onAppTransitionFinishedLocked(IBinder token) {
+ synchronized (mLock) {
+ if (!mLockAfterAppTransitionFinished) {
+ return;
+ }
+ mLockAfterAppTransitionFinished = false;
+ }
+
+ lockNow(null);
}
});
@@ -2228,7 +2245,7 @@
@Override
void execute() {
mPowerKeyHandled = true;
- interceptScreenshotChord(TAKE_SCREENSHOT_FULLSCREEN,
+ interceptScreenshotChord(
SCREENSHOT_KEY_CHORD, getScreenshotChordLongPressDelay());
}
@Override
@@ -2956,8 +2973,7 @@
break;
case KeyEvent.KEYCODE_S:
if (down && event.isMetaPressed() && event.isCtrlPressed() && repeatCount == 0) {
- interceptScreenshotChord(
- TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
+ interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
return key_consumed;
}
break;
@@ -3402,8 +3418,7 @@
break;
case KeyEvent.KEYCODE_SYSRQ:
if (down && repeatCount == 0) {
- interceptScreenshotChord(
- TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
+ interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
}
return true;
}
@@ -4344,7 +4359,7 @@
// from windowmanager. Currently, we need to ensure the setInputWindows completes,
// which would force the focus event to be queued before the current key event.
// TODO(b/70668286): post call to 'moveDisplayToTop' to mHandler instead
- Log.i(TAG, "Moving non-focused display " + displayId + " to top "
+ Log.i(TAG, "Attempting to move non-focused display " + displayId + " to top "
+ "because a key is targeting it");
mWindowManagerFuncs.moveDisplayToTopIfAllowed(displayId);
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index 3fcb08a..2fbf3fb 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -900,6 +900,7 @@
break;
case EnergyConsumerType.MOBILE_RADIO:
buckets[EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO] = true;
+ buckets[EnergyConsumerStats.POWER_BUCKET_PHONE] = true;
break;
case EnergyConsumerType.DISPLAY:
buckets[EnergyConsumerStats.POWER_BUCKET_SCREEN_ON] = true;
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index f9482dd..2fb5cec 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -178,7 +178,7 @@
// TODO: remove "tcp" from network methods, since we measure total stats.
// Current on-disk Parcel version. Must be updated when the format of the parcelable changes
- public static final int VERSION = 211;
+ public static final int VERSION = 212;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -5740,6 +5740,9 @@
HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = true;
mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
+ if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
+ scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
+ }
}
}
@@ -5750,6 +5753,7 @@
HistoryItem.STATE2_PHONE_IN_CALL_FLAG);
mPhoneOn = false;
mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
+ scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
}
}
@@ -7425,6 +7429,12 @@
@GuardedBy("this")
@Override
+ public long getPhoneEnergyConsumptionUC() {
+ return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_PHONE);
+ }
+
+ @GuardedBy("this")
+ @Override
public long getScreenOnEnergyConsumptionUC() {
return getPowerBucketConsumptionUC(EnergyConsumerStats.POWER_BUCKET_SCREEN_ON);
}
@@ -12051,17 +12061,36 @@
}
synchronized (this) {
+ final long totalRadioDurationMs =
+ mMobileRadioActiveTimer.getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
+ final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
+ mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
+ mPhoneOnTimer.setMark(elapsedRealtimeMs);
+
if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
return;
}
final SparseDoubleArray uidEstimatedConsumptionMah;
+ final long dataConsumedChargeUC;
if (consumedChargeUC > 0 && isMobileRadioEnergyConsumerSupportedLocked()) {
+ // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
+ // numerator for long rounding.
+ final long phoneConsumedChargeUC =
+ (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
+ / totalRadioDurationMs;
+ dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
+
mGlobalEnergyConsumerStats.updateStandardBucket(
- EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
+ EnergyConsumerStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
+ mGlobalEnergyConsumerStats.updateStandardBucket(
+ EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
uidEstimatedConsumptionMah = new SparseDoubleArray();
} else {
uidEstimatedConsumptionMah = null;
+ dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
}
RxTxConsumption rxTxConsumption = null;
@@ -12250,13 +12279,9 @@
totalEstimatedConsumptionMah += rxTxConsumption.txConsumptionMah;
} else {
// Estimate total active radio power consumption since last mark.
- final long totalRadioTimeMs =
- mMobileRadioActiveTimer.getTimeSinceMarkLocked(
- elapsedRealtimeMs * 1000) / 1000;
- mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
totalEstimatedConsumptionMah +=
mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
- totalRadioTimeMs);
+ totalRadioDurationMs);
// Estimate idle power consumption at each signal strength level
final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
@@ -12279,7 +12304,7 @@
mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
}
distributeEnergyToUidsLocked(EnergyConsumerStats.POWER_BUCKET_MOBILE_RADIO,
- consumedChargeUC, uidEstimatedConsumptionMah,
+ dataConsumedChargeUC, uidEstimatedConsumptionMah,
totalEstimatedConsumptionMah, elapsedRealtimeMs);
}
}
@@ -15041,6 +15066,8 @@
"record_usage_history";
public static final String KEY_PER_UID_MODEM_POWER_MODEL =
"per_uid_modem_power_model";
+ public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
+ "phone_on_external_stats_collection";
public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
"mobile_radio_active_time";
@@ -15089,6 +15116,7 @@
@PerUidModemPowerModel
private static final int DEFAULT_PER_UID_MODEM_MODEL =
PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
+ private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
/* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
@@ -15106,6 +15134,8 @@
public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
public boolean RECORD_USAGE_HISTORY = DEFAULT_RECORD_USAGE_HISTORY;
public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
+ public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
+ DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -15187,6 +15217,10 @@
"");
PER_UID_MODEM_MODEL = getPerUidModemModel(perUidModemModel);
+ PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
+ KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
+ DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
+
updateBatteryChargedDelayMsLocked();
onChange();
@@ -15256,6 +15290,8 @@
pw.println(RECORD_USAGE_HISTORY);
pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
+ pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
+ pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
}
}
diff --git a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
index 79e35c2..54f3476 100644
--- a/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
+++ b/services/core/java/com/android/server/power/stats/CpuWakeupStats.java
@@ -20,8 +20,10 @@
import static android.os.BatteryStatsInternal.CPU_WAKEUP_SUBSYSTEM_UNKNOWN;
import android.content.Context;
+import android.os.Handler;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
+import android.util.IntArray;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -32,6 +34,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IntPair;
import java.util.Arrays;
@@ -43,12 +46,16 @@
* Stores stats about CPU wakeups and tries to attribute them to subsystems and uids.
*/
public class CpuWakeupStats {
+ private static final String TAG = "CpuWakeupStats";
+
private static final String SUBSYSTEM_ALARM_STRING = "Alarm";
@VisibleForTesting
static final long WAKEUP_RETENTION_MS = 3 * 24 * 60 * 60_000; // 3 days.
@VisibleForTesting
static final long WAKEUP_REASON_HALF_WINDOW_MS = 500;
+ private static final long WAKEUP_WRITE_DELAY_MS = 2 * 60 * 1000; // 2 minutes.
+ private final Handler mHandler;
private final IrqDeviceMap mIrqDeviceMap;
private final WakingActivityHistory mRecentWakingActivity = new WakingActivityHistory();
@@ -58,8 +65,58 @@
final TimeSparseArray<SparseArray<SparseBooleanArray>> mWakeupAttribution =
new TimeSparseArray<>();
- public CpuWakeupStats(Context context, int mapRes) {
+ public CpuWakeupStats(Context context, int mapRes, Handler handler) {
mIrqDeviceMap = IrqDeviceMap.getInstance(context, mapRes);
+ mHandler = handler;
+ }
+
+ private static int subsystemToStatsReason(int subsystem) {
+ switch (subsystem) {
+ case CPU_WAKEUP_SUBSYSTEM_ALARM:
+ return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__ALARM;
+ }
+ return FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN;
+ }
+
+ private synchronized void logWakeupToStatsLog(Wakeup wakeupToLog) {
+ if (ArrayUtils.isEmpty(wakeupToLog.mDevices)) {
+ FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED,
+ FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__TYPE__TYPE_UNKNOWN,
+ FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__REASON__UNKNOWN,
+ null,
+ wakeupToLog.mElapsedMillis);
+ return;
+ }
+
+ final SparseArray<SparseBooleanArray> wakeupAttribution = mWakeupAttribution.get(
+ wakeupToLog.mElapsedMillis);
+ if (wakeupAttribution == null) {
+ // This is not expected but can theoretically happen in extreme situations, e.g. if we
+ // remove the wakeup before the handler gets to process this message.
+ Slog.wtf(TAG, "Unexpected null attribution found for " + wakeupToLog);
+ return;
+ }
+ for (int i = 0; i < wakeupAttribution.size(); i++) {
+ final int subsystem = wakeupAttribution.keyAt(i);
+ final SparseBooleanArray uidMap = wakeupAttribution.valueAt(i);
+ final int[] uids;
+ if (uidMap == null || uidMap.size() == 0) {
+ uids = new int[0];
+ } else {
+ final IntArray tmp = new IntArray(uidMap.size());
+ for (int j = 0; j < uidMap.size(); j++) {
+ if (uidMap.valueAt(j)) {
+ tmp.add(uidMap.keyAt(j));
+ }
+ }
+ uids = tmp.toArray();
+ }
+ FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED,
+ FrameworkStatsLog.KERNEL_WAKEUP_ATTRIBUTED__TYPE__TYPE_IRQ,
+ subsystemToStatsReason(subsystem),
+ uids,
+ wakeupToLog.mElapsedMillis);
+ }
}
/** Notes a wakeup reason as reported by SuspendControlService to battery stats. */
@@ -83,6 +140,7 @@
for (int i = lastIdx; i >= 0; i--) {
mWakeupAttribution.removeAt(i);
}
+ mHandler.postDelayed(() -> logWakeupToStatsLog(parsedWakeup), WAKEUP_WRITE_DELAY_MS);
}
/** Notes a waking activity that could have potentially woken up the CPU. */
diff --git a/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java b/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java
index bb89333..79ec6e2 100644
--- a/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java
+++ b/services/core/java/com/android/server/power/stats/PhonePowerCalculator.java
@@ -42,14 +42,27 @@
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+ final long energyConsumerUC = batteryStats.getPhoneEnergyConsumptionUC();
+ final int powerModel = getPowerModel(energyConsumerUC, query);
+
final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
- if (phoneOnPower != 0) {
- builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower)
- .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
+
+ final double phoneOnPower;
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION:
+ phoneOnPower = uCtoMah(energyConsumerUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
}
+
+ if (phoneOnPower == 0.0) return;
+
+ builder.getAggregateBatteryConsumerBuilder(
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower, powerModel)
+ .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 6c616e0..b3e915a 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -170,6 +170,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.StatsEventOutput;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
import com.android.internal.os.KernelAllocationStats;
@@ -613,12 +614,19 @@
}
case FrameworkStatsLog.PROC_STATS:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_ALL, atomTag, data);
+ return pullProcStatsLocked(atomTag, data);
}
case FrameworkStatsLog.PROC_STATS_PKG_PROC:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_PKG_PROC_STATS, atomTag,
- data);
+ return pullProcStatsLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_STATE:
+ synchronized (mProcStatsLock) {
+ return pullProcessStateLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_ASSOCIATION:
+ synchronized (mProcStatsLock) {
+ return pullProcessAssociationLocked(atomTag, data);
}
case FrameworkStatsLog.DISK_IO:
synchronized (mDiskIoLock) {
@@ -891,6 +899,8 @@
registerNumFacesEnrolled();
registerProcStats();
registerProcStatsPkgProc();
+ registerProcessState();
+ registerProcessAssociation();
registerDiskIO();
registerPowerProfile();
registerProcessCpuTime();
@@ -2884,59 +2894,138 @@
);
}
- private int pullProcStatsLocked(int section, int atomTag, List<StatsEvent> pulledData) {
+ private void registerProcessState() {
+ int tagId = FrameworkStatsLog.PROCESS_STATE;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ private void registerProcessAssociation() {
+ int tagId = FrameworkStatsLog.PROCESS_ASSOCIATION;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private ProcessStats getStatsFromProcessStatsService(int atomTag) {
IProcessStats processStatsService = getIProcessStatsService();
if (processStatsService == null) {
- return StatsManager.PULL_SKIP;
+ return null;
}
-
final long token = Binder.clearCallingIdentity();
try {
// force procstats to flush & combine old files into one store
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
-
- ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
- for (int i = 0; i < protoStreams.length; i++) {
- protoStreams[i] = new ProtoOutputStream();
- }
-
+ long lastHighWaterMark = readProcStatsHighWaterMark(atomTag);
ProcessStats procStats = new ProcessStats(false);
// Force processStatsService to aggregate all in-storage and in-memory data.
- long highWaterMark = processStatsService.getCommittedStatsMerged(
- lastHighWaterMark, section, true, null, procStats);
- procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
-
- for (int i = 0; i < protoStreams.length; i++) {
- byte[] bytes = protoStreams[i].getBytes(); // cache the value
- if (bytes.length > 0) {
- pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, bytes,
- // This is a shard ID, and is specified in the metric definition to be
- // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE to
- // keep all the shards, as it thinks each shard is a different dimension
- // of data.
- i));
- }
- }
-
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
+ long highWaterMark =
+ processStatsService.getCommittedStatsMerged(
+ lastHighWaterMark,
+ ProcessStats.REPORT_ALL, // ignored since committedStats below is null.
+ true,
+ null, // committedStats
+ procStats);
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + lastHighWaterMark)
.delete();
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + highWaterMark)
.createNewFile();
+ return procStats;
} catch (RemoteException | IOException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
- return StatsManager.PULL_SKIP;
+ return null;
} finally {
Binder.restoreCallingIdentity(token);
}
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcStatsLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
+ for (int i = 0; i < protoStreams.length; i++) {
+ protoStreams[i] = new ProtoOutputStream();
+ }
+ procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
+ for (int i = 0; i < protoStreams.length; i++) {
+ byte[] bytes = protoStreams[i].getBytes(); // cache the value
+ if (bytes.length > 0) {
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ bytes,
+ // This is a shard ID, and is specified in the metric definition to
+ // be
+ // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE
+ // to
+ // keep all the shards, as it thinks each shard is a different
+ // dimension
+ // of data.
+ i));
+ }
+ }
return StatsManager.PULL_SUCCESS;
}
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessStateLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessState(atomTag, new StatsEventOutput(pulledData));
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessAssociationLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessAssociation(atomTag, new StatsEventOutput(pulledData));
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ private String highWaterMarkFilePrefix(int atomTag) {
+ // For backward compatibility, use the legacy ProcessStats enum value as the prefix for
+ // PROC_STATS and PROC_STATS_PKG_PROC.
+ if (atomTag == FrameworkStatsLog.PROC_STATS) {
+ return String.valueOf(ProcessStats.REPORT_ALL);
+ }
+ if (atomTag == FrameworkStatsLog.PROC_STATS_PKG_PROC) {
+ return String.valueOf(ProcessStats.REPORT_PKG_PROC_STATS);
+ }
+ return "atom-" + atomTag;
+ }
+
// read high watermark for section
- private long readProcStatsHighWaterMark(int section) {
+ private long readProcStatsHighWaterMark(int atomTag) {
try {
- File[] files = mBaseDir.listFiles((d, name) -> {
- return name.toLowerCase().startsWith(String.valueOf(section) + '_');
- });
+ File[] files =
+ mBaseDir.listFiles(
+ (d, name) -> {
+ return name.toLowerCase()
+ .startsWith(highWaterMarkFilePrefix(atomTag) + '_');
+ });
if (files == null || files.length == 0) {
return 0;
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 075bac1..b146767 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -87,7 +87,6 @@
import android.os.IInterface;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
-import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -2169,12 +2168,14 @@
@Override
public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
final int which, Bundle outParams, int wallpaperUserId) {
- return getWallpaperWithFeature(callingPkg, null, cb, which, outParams, wallpaperUserId);
+ return getWallpaperWithFeature(callingPkg, null, cb, which, outParams,
+ wallpaperUserId, /* getCropped= */ true);
}
@Override
public ParcelFileDescriptor getWallpaperWithFeature(String callingPkg, String callingFeatureId,
- IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) {
+ IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId,
+ boolean getCropped) {
final boolean hasPrivilege = hasPermission(READ_WALLPAPER_INTERNAL);
if (!hasPrivilege) {
mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true,
@@ -2209,10 +2210,14 @@
if (cb != null) {
wallpaper.callbacks.register(cb);
}
- if (!wallpaper.cropFile.exists()) {
+
+ File fileToReturn = getCropped ? wallpaper.cropFile : wallpaper.wallpaperFile;
+
+ if (!fileToReturn.exists()) {
return null;
}
- return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
+
+ return ParcelFileDescriptor.open(fileToReturn, MODE_READ_ONLY);
} catch (FileNotFoundException e) {
/* Shouldn't happen as we check to see if the file exists */
Slog.w(TAG, "Error getting wallpaper", e);
@@ -2250,6 +2255,25 @@
}
@Override
+ public ParcelFileDescriptor getWallpaperInfoFile(int userId) {
+ synchronized (mLock) {
+ try {
+ File file = new File(getWallpaperDir(userId), WALLPAPER_INFO);
+
+ if (!file.exists()) {
+ return null;
+ }
+
+ return ParcelFileDescriptor.open(file, MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ /* Shouldn't happen as we check to see if the file exists */
+ Slog.w(TAG, "Error getting wallpaper info file", e);
+ }
+ return null;
+ }
+ }
+
+ @Override
public int getWallpaperIdForUser(int which, int userId) {
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
@@ -3201,10 +3225,6 @@
@Override
public boolean isWallpaperBackupEligible(int which, int userId) {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("Only the system may call isWallpaperBackupEligible");
- }
-
WallpaperData wallpaper = (which == FLAG_LOCK)
? mLockWallpaperMap.get(userId)
: mWallpaperMap.get(userId);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6abd3d7..90ac1aa 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -932,6 +932,8 @@
// task and directly above this ActivityRecord. This field is updated whenever a new activity
// is launched from this ActivityRecord. Touches are always allowed within the same uid.
int mAllowedTouchUid;
+ // Whether client has requested a scene transition when exiting.
+ final boolean mHasSceneTransition;
// Whether the ActivityEmbedding is enabled on the app.
private final boolean mAppActivityEmbeddingSplitsEnabled;
@@ -2091,6 +2093,10 @@
if (options != null) {
setOptions(options);
+ // The result receiver is the transition receiver, which will handle the shared element
+ // exit transition.
+ mHasSceneTransition = options.getAnimationType() == ANIM_SCENE_TRANSITION
+ && options.getResultReceiver() != null;
final PendingIntent usageReport = options.getUsageTimeReport();
if (usageReport != null) {
appTimeTracker = new AppTimeTracker(usageReport);
@@ -2103,6 +2109,8 @@
mHandoverLaunchDisplayId = options.getLaunchDisplayId();
mLaunchCookie = options.getLaunchCookie();
mLaunchRootTask = options.getLaunchRootTask();
+ } else {
+ mHasSceneTransition = false;
}
mPersistentState = persistentState;
@@ -5249,9 +5257,9 @@
transferStartingWindowFromHiddenAboveTokenIfNeeded();
}
- // If in a transition, defer commits for activities that are going invisible
- if (!visible && inTransition()) {
- if (mTransitionController.inPlayingTransition(this)
+ // Defer committing visibility until transition starts.
+ if (inTransition()) {
+ if (!visible && mTransitionController.inPlayingTransition(this)
&& mTransitionController.isCollecting(this)) {
mTransitionChangeFlags |= FLAG_IS_OCCLUDED;
}
@@ -5501,6 +5509,17 @@
}
}
+ /** Updates draw state and shows drawn windows. */
+ void commitFinishDrawing(SurfaceControl.Transaction t) {
+ boolean committed = false;
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ committed |= mChildren.get(i).commitFinishDrawing(t);
+ }
+ if (committed) {
+ requestUpdateWallpaperIfNeeded();
+ }
+ }
+
/**
* Check if visibility of this {@link ActivityRecord} should be updated as part of an app
* transition.
@@ -6559,12 +6578,29 @@
updateReportedVisibilityLocked();
}
+ /**
+ * Sets whether something has been visible in the task and returns {@code true} if the state
+ * is changed from invisible to visible.
+ */
+ private boolean setTaskHasBeenVisible() {
+ final boolean wasTaskVisible = task.getHasBeenVisible();
+ if (wasTaskVisible) {
+ return false;
+ }
+ if (inTransition()) {
+ // The deferring will be canceled until transition is ready so it won't dispatch
+ // intermediate states to organizer.
+ task.setDeferTaskAppear(true);
+ }
+ task.setHasBeenVisible(true);
+ return true;
+ }
+
void onStartingWindowDrawn() {
boolean wasTaskVisible = false;
if (task != null) {
mSplashScreenStyleSolidColor = true;
- wasTaskVisible = task.getHasBeenVisible();
- task.setHasBeenVisible(true);
+ wasTaskVisible = !setTaskHasBeenVisible();
}
// The transition may not be executed if the starting process hasn't attached. But if the
@@ -6602,7 +6638,7 @@
}
finishLaunchTickingLocked();
if (task != null) {
- task.setHasBeenVisible(true);
+ setTaskHasBeenVisible();
}
// Clear indicated launch root task because there's no trampoline activity to expect after
// the windows are drawn.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index bd4f1a6..2bd9052 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -24,6 +24,7 @@
import android.app.BackgroundStartPrivileges;
import android.app.IActivityManager;
import android.app.IApplicationThread;
+import android.app.ITaskStackListener;
import android.app.ProfilerInfo;
import android.content.ComponentName;
import android.content.IIntentSender;
@@ -740,4 +741,10 @@
*/
public abstract void restartTaskActivityProcessIfVisible(
int taskId, @NonNull String packageName);
+
+ /** Sets the task stack listener that gets callbacks when a task stack changes. */
+ public abstract void registerTaskStackListener(ITaskStackListener listener);
+
+ /** Unregister a task stack listener so that it stops receiving callbacks. */;
+ public abstract void unregisterTaskStackListener(ITaskStackListener listener);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 070ad2d..a927ed3 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4756,6 +4756,7 @@
mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false);
}
mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
+ mTaskSupervisor.mRecentTasks.add(task);
}
applyUpdateLockStateLocked(r);
@@ -6915,5 +6916,17 @@
activity.restartProcessIfVisible();
}
}
+
+ /** Sets the task stack listener that gets callbacks when a task stack changes. */
+ @Override
+ public void registerTaskStackListener(ITaskStackListener listener) {
+ ActivityTaskManagerService.this.registerTaskStackListener(listener);
+ }
+
+ /** Unregister a task stack listener so that it stops receiving callbacks. */
+ @Override
+ public void unregisterTaskStackListener(ITaskStackListener listener) {
+ ActivityTaskManagerService.this.unregisterTaskStackListener(listener);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 14131e6..cc71155 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -218,17 +218,19 @@
// - We don't have any ActivityRecord or Task to animate.
// - The IME is opened, and we just need to close it.
// - The home activity is the focused activity.
+ // - The current activity will do shared element transition when exiting.
if (backType == BackNavigationInfo.TYPE_CALLBACK
|| currentActivity == null
|| currentTask == null
- || currentActivity.isActivityTypeHome()) {
+ || currentActivity.isActivityTypeHome()
+ || currentActivity.mHasSceneTransition) {
infoBuilder.setType(BackNavigationInfo.TYPE_CALLBACK);
final WindowState finalFocusedWindow = window;
infoBuilder.setOnBackNavigationDone(new RemoteCallback(result ->
onBackNavigationDone(result, finalFocusedWindow,
BackNavigationInfo.TYPE_CALLBACK)));
- mLastBackType = backType;
- return infoBuilder.setType(backType).build();
+ mLastBackType = BackNavigationInfo.TYPE_CALLBACK;
+ return infoBuilder.build();
}
mBackAnimationInProgress = true;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 63d6509..0bd59a8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -6841,12 +6841,12 @@
public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
mRemoteInsetsController.showInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_SHOW_INSETS);
}
}
@@ -6855,12 +6855,12 @@
public void hideInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
mRemoteInsetsController.hideInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver hideInsets", e);
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_WM_REMOTE_INSETS_CONTROL_TARGET_HIDE_INSETS);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a68d7af..cfcf459 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -129,6 +129,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.util.ScreenshotRequest;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.view.AppearanceRegion;
import com.android.internal.widget.PointerLocationView;
@@ -2451,8 +2452,9 @@
*/
public void takeScreenshot(int screenshotType, int source) {
if (mScreenshotHelper != null) {
- mScreenshotHelper.takeScreenshot(screenshotType,
- source, mHandler, null /* completionConsumer */);
+ ScreenshotRequest request =
+ new ScreenshotRequest.Builder(screenshotType, source).build();
+ mScreenshotHelper.takeScreenshot(request, mHandler, null /* completionConsumer */);
}
}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 60e2e95..85938e3 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -182,8 +182,7 @@
boolean targetChanged = isTargetChangedWithinActivity(imeTarget);
mImeRequester = imeTarget;
// There was still a stats token, so that request presumably failed.
- ImeTracker.forLogging().onFailed(
- mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+ ImeTracker.get().onFailed(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
mImeRequesterStatsToken = statsToken;
if (targetChanged) {
// target changed, check if new target can show IME.
@@ -198,12 +197,12 @@
ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeRequester.getWindow() == null
? mImeRequester : mImeRequester.getWindow().getName());
mShowImeRunner = () -> {
- ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
+ ImeTracker.get().onProgress(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner");
// Target should still be the same.
if (isReadyToShowIme()) {
- ImeTracker.forLogging().onProgress(mImeRequesterStatsToken,
+ ImeTracker.get().onProgress(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_READY);
final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
@@ -220,7 +219,7 @@
? mImeRequester.getWindow().getName() : ""));
}
} else {
- ImeTracker.forLogging().onFailed(mImeRequesterStatsToken,
+ ImeTracker.get().onFailed(mImeRequesterStatsToken,
ImeTracker.PHASE_WM_SHOW_IME_READY);
}
// Clear token here so we don't report an error in abortShowImePostLayout().
@@ -259,8 +258,7 @@
mImeRequester = null;
mIsImeLayoutDrawn = false;
mShowImeRunner = null;
- ImeTracker.forLogging().onCancelled(
- mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
+ ImeTracker.get().onCancelled(mImeRequesterStatsToken, ImeTracker.PHASE_WM_SHOW_IME_RUNNER);
mImeRequesterStatsToken = null;
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 874f942..1df534f 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -707,8 +707,7 @@
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) {
super(show, false /* hasCallbacks */, types, BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
- false /* disable */, 0 /* floatingImeBottomInsets */,
- null /* loggingListener */, null /* jankContext */);
+ false /* disable */, 0 /* floatingImeBottomInsets */, null);
mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index f916ee4..800fe09 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -197,6 +197,12 @@
// Whether using split screen aspect ratio as a default aspect ratio for unresizable apps.
private boolean mIsSplitScreenAspectRatioForUnresizableAppsEnabled;
+ // Whether using display aspect ratio as a default aspect ratio for all letterboxed apps.
+ // mIsSplitScreenAspectRatioForUnresizableAppsEnabled and
+ // config_letterboxDefaultMinAspectRatioForUnresizableApps take priority over this for
+ // unresizable apps
+ private boolean mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox;
+
// Whether letterboxing strategy is enabled for translucent activities. If {@value false}
// all the feature is disabled
private boolean mTranslucentLetterboxingEnabled;
@@ -288,6 +294,9 @@
R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps));
mIsSplitScreenAspectRatioForUnresizableAppsEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
+ mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox = mContext.getResources()
+ .getBoolean(R.bool
+ .config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled);
mTranslucentLetterboxingEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsEnabledForTranslucentActivities);
mIsCameraCompatTreatmentEnabled = mContext.getResources().getBoolean(
@@ -943,6 +952,13 @@
}
/**
+ * Whether using display aspect ratio as a default aspect ratio for all letterboxed apps.
+ */
+ boolean getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox() {
+ return mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox;
+ }
+
+ /**
* Overrides whether using split screen aspect ratio as a default aspect ratio for unresizable
* apps.
*/
@@ -951,6 +967,14 @@
}
/**
+ * Overrides whether using display aspect ratio as a default aspect ratio for all letterboxed
+ * apps.
+ */
+ void setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(boolean enabled) {
+ mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox = enabled;
+ }
+
+ /**
* Resets whether using split screen aspect ratio as a default aspect ratio for unresizable
* apps {@link R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled}.
*/
@@ -959,6 +983,16 @@
R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
}
+ /**
+ * Resets whether using display aspect ratio as a default aspect ratio for all letterboxed
+ * apps {@link R.bool.config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled}.
+ */
+ void resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox() {
+ mIsDisplayAspectRatioEnabledForFixedOrientationLetterbox = mContext.getResources()
+ .getBoolean(R.bool
+ .config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled);
+ }
+
boolean isTranslucentLetterboxingEnabled() {
return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
&& isTranslucentLetterboxingAllowed());
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 9c43c1d..67e188f 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -584,7 +584,7 @@
? getSplitScreenAspectRatio()
: mActivityRecord.shouldCreateCompatDisplayInsets()
? getDefaultMinAspectRatioForUnresizableApps()
- : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ : getDefaultMinAspectRatio();
}
private float getDefaultMinAspectRatioForUnresizableApps() {
@@ -593,7 +593,7 @@
return mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps()
> MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
? mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps()
- : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ : getDefaultMinAspectRatio();
}
return getSplitScreenAspectRatio();
@@ -621,6 +621,16 @@
return computeAspectRatio(bounds);
}
+ private float getDefaultMinAspectRatio() {
+ final DisplayContent displayContent = mActivityRecord.getDisplayContent();
+ if (displayContent == null
+ || !mLetterboxConfiguration
+ .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()) {
+ return mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
+ }
+ return computeAspectRatio(new Rect(displayContent.getBounds()));
+ }
+
Resources getResources() {
return mActivityRecord.mWmService.mContext.getResources();
}
@@ -1014,6 +1024,9 @@
+ mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps());
pw.println(prefix + " isSplitScreenAspectRatioForUnresizableAppsEnabled="
+ mLetterboxConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled());
+ pw.println(prefix + " isDisplayAspectRatioEnabledForFixedOrientationLetterbox="
+ + mLetterboxConfiguration
+ .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox());
}
/**
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 15a5ebf..97e0b1e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -310,6 +310,11 @@
}
}
+ @Override
+ public void performHapticFeedbackAsync(int effectId, boolean always) {
+ performHapticFeedback(effectId, always);
+ }
+
/* Drag/drop */
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b7021c8..a76d836 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4148,21 +4148,28 @@
void setHasBeenVisible(boolean hasBeenVisible) {
mHasBeenVisible = hasBeenVisible;
- if (hasBeenVisible) {
- if (!mDeferTaskAppear) sendTaskAppeared();
- if (!isRootTask()) {
- getRootTask().setHasBeenVisible(true);
+ if (!hasBeenVisible || mDeferTaskAppear) {
+ return;
+ }
+ sendTaskAppeared();
+ for (WindowContainer<?> parent = getParent(); parent != null; parent = parent.getParent()) {
+ final Task parentTask = parent.asTask();
+ if (parentTask == null) {
+ break;
}
+ parentTask.setHasBeenVisible(true);
}
}
+
boolean getHasBeenVisible() {
return mHasBeenVisible;
}
void setDeferTaskAppear(boolean deferTaskAppear) {
+ final boolean wasDeferred = mDeferTaskAppear;
mDeferTaskAppear = deferTaskAppear;
- if (!mDeferTaskAppear) {
+ if (wasDeferred && !deferTaskAppear) {
sendTaskAppeared();
}
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index cd23959..7d3367f 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -70,6 +70,7 @@
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -211,6 +212,8 @@
private IContainerFreezer mContainerFreezer = null;
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ final TransitionController.Logger mLogger = new TransitionController.Logger();
+
Transition(@TransitionType int type, @TransitionFlags int flags,
TransitionController controller, BLASTSyncEngine syncEngine) {
mType = type;
@@ -219,6 +222,8 @@
mSyncEngine = syncEngine;
mToken = new Token(this);
+ mLogger.mCreateWallTimeMs = System.currentTimeMillis();
+ mLogger.mCreateTimeNs = SystemClock.uptimeNanos();
controller.mTransitionTracer.logState(this);
}
@@ -380,6 +385,8 @@
mState = STATE_COLLECTING;
mSyncId = mSyncEngine.startSyncSet(this, timeoutMs, TAG, method);
+ mLogger.mSyncId = mSyncId;
+ mLogger.mCollectTimeNs = SystemClock.uptimeNanos();
mController.mTransitionTracer.logState(this);
}
@@ -399,6 +406,7 @@
mSyncId);
applyReady();
+ mLogger.mStartTimeNs = SystemClock.uptimeNanos();
mController.mTransitionTracer.logState(this);
mController.updateAnimatingState(mTmpTransaction);
@@ -608,6 +616,7 @@
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Set transition ready=%b %d", ready, mSyncId);
mSyncEngine.setReady(mSyncId, ready);
+ if (ready) mLogger.mReadyTimeNs = SystemClock.uptimeNanos();
}
/**
@@ -759,6 +768,8 @@
Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, TRACE_NAME_PLAY_TRANSITION,
System.identityHashCode(this));
}
+ mLogger.mFinishTimeNs = SystemClock.uptimeNanos();
+ mController.mLoggerHandler.post(mLogger::logOnFinish);
// Close the transactions now. They were originally copied to Shell in case we needed to
// apply them due to a remote failure. Since we don't need to apply them anymore, free them
// immediately.
@@ -845,7 +856,7 @@
final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
if (ar == null || !ar.isVisible() || ar.getParent() == null) continue;
if (inputSinkTransaction == null) {
- inputSinkTransaction = new SurfaceControl.Transaction();
+ inputSinkTransaction = ar.mWmService.mTransactionFactory.get();
}
ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(inputSinkTransaction);
}
@@ -961,6 +972,12 @@
// time being, we don't have full cross-display transitions so it isn't a problem.
final DisplayContent dc = mTargetDisplays.get(0);
+ // Commit the visibility of visible activities before calculateTransitionInfo(), so the
+ // TaskInfo can be visible. Also it needs to be done before moveToPlaying(), otherwise
+ // ActivityRecord#canShowWindows() may reject to show its window. The visibility also
+ // needs to be updated for STATE_ABORT.
+ commitVisibleActivities(transaction);
+
if (mState == STATE_ABORT) {
mController.abort(this);
dc.getPendingTransaction().merge(transaction);
@@ -1082,6 +1099,8 @@
try {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Calling onTransitionReady: %s", info);
+ mLogger.mSendTimeNs = SystemClock.uptimeNanos();
+ mLogger.mInfo = info;
mController.getTransitionPlayer().onTransitionReady(
mToken, info, transaction, mFinishTransaction);
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
@@ -1097,6 +1116,7 @@
// No player registered, so just finish/apply immediately
cleanUpOnFailure();
}
+ mController.mLoggerHandler.post(mLogger::logOnSend);
mOverrideOptions = null;
reportStartReasonsToLogger();
@@ -1132,6 +1152,22 @@
}
}
+ /** The transition is ready to play. Make the start transaction show the surfaces. */
+ private void commitVisibleActivities(SurfaceControl.Transaction transaction) {
+ for (int i = mParticipants.size() - 1; i >= 0; --i) {
+ final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
+ if (ar == null || ar.getTask() == null) {
+ continue;
+ }
+ if (ar.isVisibleRequested()) {
+ ar.commitVisibility(true /* visible */, false /* performLayout */,
+ true /* fromTransition */);
+ ar.commitFinishDrawing(transaction);
+ }
+ ar.getTask().setDeferTaskAppear(false);
+ }
+ }
+
/** @see RecentsAnimationController#attachNavigationBarToApp */
private void handleLegacyRecentsStartBehavior(DisplayContent dc, TransitionInfo info) {
if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 73cd251..5e116ba 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -30,6 +30,7 @@
import android.app.ActivityManager;
import android.app.IApplicationThread;
import android.app.WindowConfiguration;
+import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.RemoteException;
@@ -38,6 +39,7 @@
import android.os.Trace;
import android.util.ArrayMap;
import android.util.Slog;
+import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -46,11 +48,13 @@
import android.window.RemoteTransition;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -120,6 +124,8 @@
private boolean mAnimatingState = false;
+ final Handler mLoggerHandler = FgThread.getHandler();
+
TransitionController(ActivityTaskManagerService atm,
TaskSnapshotController taskSnapshotController,
TransitionTracer transitionTracer) {
@@ -462,9 +468,11 @@
info = new ActivityManager.RunningTaskInfo();
startTask.fillTaskInfo(info);
}
- mTransitionPlayer.requestStartTransition(transition.getToken(),
- new TransitionRequestInfo(transition.mType, info, remoteTransition,
- displayChange));
+ final TransitionRequestInfo request = new TransitionRequestInfo(
+ transition.mType, info, remoteTransition, displayChange);
+ transition.mLogger.mRequestTimeNs = SystemClock.uptimeNanos();
+ transition.mLogger.mRequest = request;
+ mTransitionPlayer.requestStartTransition(transition.getToken(), request);
transition.setRemoteTransition(remoteTransition);
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting transition", e);
@@ -847,6 +855,66 @@
}
}
+ /**
+ * Data-class to store recorded events/info for a transition. This allows us to defer the
+ * actual logging until the system isn't busy. This also records some common metrics to see
+ * delays at-a-glance.
+ *
+ * Beside `mCreateWallTimeMs`, all times are elapsed times and will all be reported relative
+ * to when the transition was created.
+ */
+ static class Logger {
+ long mCreateWallTimeMs;
+ long mCreateTimeNs;
+ long mRequestTimeNs;
+ long mCollectTimeNs;
+ long mStartTimeNs;
+ long mReadyTimeNs;
+ long mSendTimeNs;
+ long mFinishTimeNs;
+ TransitionRequestInfo mRequest;
+ WindowContainerTransaction mStartWCT;
+ int mSyncId;
+ TransitionInfo mInfo;
+
+ private String buildOnSendLog() {
+ StringBuilder sb = new StringBuilder("Sent Transition #").append(mSyncId)
+ .append(" createdAt=").append(TimeUtils.logTimeOfDay(mCreateWallTimeMs));
+ if (mRequest != null) {
+ sb.append(" via request=").append(mRequest);
+ }
+ return sb.toString();
+ }
+
+ void logOnSend() {
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "%s", buildOnSendLog());
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, " startWCT=%s", mStartWCT);
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, " info=%s", mInfo);
+ }
+
+ private static String toMsString(long nanos) {
+ return ((double) Math.round((double) nanos / 1000) / 1000) + "ms";
+ }
+
+ private String buildOnFinishLog() {
+ StringBuilder sb = new StringBuilder("Finish Transition #").append(mSyncId)
+ .append(": created at ").append(TimeUtils.logTimeOfDay(mCreateWallTimeMs));
+ sb.append(" collect-started=").append(toMsString(mCollectTimeNs - mCreateTimeNs));
+ if (mRequestTimeNs != 0) {
+ sb.append(" request-sent=").append(toMsString(mRequestTimeNs - mCreateTimeNs));
+ }
+ sb.append(" started=").append(toMsString(mStartTimeNs - mCreateTimeNs));
+ sb.append(" ready=").append(toMsString(mReadyTimeNs - mCreateTimeNs));
+ sb.append(" sent=").append(toMsString(mSendTimeNs - mCreateTimeNs));
+ sb.append(" finished=").append(toMsString(mFinishTimeNs - mCreateTimeNs));
+ return sb.toString();
+ }
+
+ void logOnFinish() {
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS_MIN, "%s", buildOnFinishLog());
+ }
+ }
+
static class TransitionMetricsReporter extends ITransitionMetricsReporter.Stub {
private final ArrayMap<IBinder, LongConsumer> mMetricConsumers = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 18ad43c..8767096 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8087,14 +8087,14 @@
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
}
if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ",
dc.getImeTarget(IME_TARGET_CONTROL));
dc.getImeTarget(IME_TARGET_CONTROL).hideInsets(WindowInsets.Type.ime(),
true /* fromIme */, statsToken);
} else {
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_WM_HAS_IME_INSETS_CONTROL_TARGET);
}
if (dc != null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index e2c9c17..e931175 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -970,6 +970,10 @@
runSetBooleanFlag(pw, mLetterboxConfiguration
::setIsSplitScreenAspectRatioForUnresizableAppsEnabled);
break;
+ case "--isDisplayAspectRatioEnabledForFixedOrientationLetterbox":
+ runSetBooleanFlag(pw, mLetterboxConfiguration
+ ::setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox);
+ break;
case "--isTranslucentLetterboxingEnabled":
runSetBooleanFlag(pw, mLetterboxConfiguration
::setTranslucentLetterboxingOverrideEnabled);
@@ -1045,6 +1049,10 @@
mLetterboxConfiguration
.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
break;
+ case "IsDisplayAspectRatioEnabledForFixedOrientationLetterbox":
+ mLetterboxConfiguration
+ .resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
+ break;
case "isTranslucentLetterboxingEnabled":
mLetterboxConfiguration.resetTranslucentLetterboxingEnabled();
break;
@@ -1155,6 +1163,7 @@
mLetterboxConfiguration.resetDefaultPositionForVerticalReachability();
mLetterboxConfiguration.resetIsEducationEnabled();
mLetterboxConfiguration.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
+ mLetterboxConfiguration.resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
mLetterboxConfiguration.resetTranslucentLetterboxingEnabled();
mLetterboxConfiguration.resetCameraCompatRefreshEnabled();
mLetterboxConfiguration.resetCameraCompatRefreshCycleThroughStopEnabled();
@@ -1202,7 +1211,9 @@
pw.println("Is using split screen aspect ratio as aspect ratio for unresizable apps: "
+ mLetterboxConfiguration
.getIsSplitScreenAspectRatioForUnresizableAppsEnabled());
-
+ pw.println("Is using display aspect ratio as aspect ratio for all letterboxed apps: "
+ + mLetterboxConfiguration
+ .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox());
pw.println(" Is activity \"refresh\" in camera compatibility treatment enabled: "
+ mLetterboxConfiguration.isCameraCompatRefreshEnabled());
pw.println(" Refresh using \"stopped -> resumed\" cycle: "
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 6a1adb4..5c68b12 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -318,6 +318,7 @@
transition = mTransitionController.createTransition(type);
}
transition.start();
+ transition.mLogger.mStartWCT = wct;
applyTransaction(wct, -1 /*syncId*/, transition, caller);
if (needsSetReady) {
transition.setAllReady();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7a0070b..223352e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3993,12 +3993,12 @@
public void showInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
mClient.showInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver showInsets", e);
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_SHOW_INSETS);
}
}
@@ -4007,12 +4007,12 @@
public void hideInsets(@InsetsType int types, boolean fromIme,
@Nullable ImeTracker.Token statsToken) {
try {
- ImeTracker.forLogging().onProgress(statsToken,
+ ImeTracker.get().onProgress(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
mClient.hideInsets(types, fromIme, statsToken);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver hideInsets", e);
- ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.get().onFailed(statsToken,
ImeTracker.PHASE_WM_WINDOW_INSETS_CONTROL_TARGET_HIDE_INSETS);
}
}
@@ -4616,6 +4616,19 @@
}
}
+ /** Makes the surface of drawn window (COMMIT_DRAW_PENDING) to be visible. */
+ boolean commitFinishDrawing(SurfaceControl.Transaction t) {
+ boolean committed = mWinAnimator.commitFinishDrawingLocked();
+ if (committed) {
+ // Ensure that the visibility of buffer layer is set.
+ mWinAnimator.prepareSurfaceLocked(t);
+ }
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ committed |= mChildren.get(i).commitFinishDrawing(t);
+ }
+ return committed;
+ }
+
// This must be called while inside a transaction.
boolean performShowLocked() {
if (!showToCurrentUser()) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 40e74b1..7c73768 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1489,7 +1489,7 @@
mServiceObj, gServiceClassInfo.getContextForDisplay, displayId));
for (int32_t iconId = static_cast<int32_t>(PointerIconStyle::TYPE_CONTEXT_MENU);
- iconId <= static_cast<int32_t>(PointerIconStyle::TYPE_GRABBING); ++iconId) {
+ iconId <= static_cast<int32_t>(PointerIconStyle::TYPE_HANDWRITING); ++iconId) {
const PointerIconStyle pointerIconStyle = static_cast<PointerIconStyle>(iconId);
PointerIcon pointerIcon;
loadSystemIconAsSpriteWithPointerIcon(env, displayContext.get(), pointerIconStyle,
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index acfa491..351afb9 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -35,7 +35,7 @@
import java.util.ArrayList;
/**
- * Central session for a single {@link CredentialManager#executeCreateCredential} request.
+ * Central session for a single {@link CredentialManager#createCredential} request.
* This class listens to the responses from providers, and the UX app, and updates the
* provider(s) state maintained in {@link ProviderCreateSession}.
*/
@@ -107,9 +107,14 @@
}
@Override
- public void onUiCancellation() {
- respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_USER_CANCELED,
- "User cancelled the selector");
+ public void onUiCancellation(boolean isUserCancellation) {
+ if (isUserCancellation) {
+ respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_USER_CANCELED,
+ "User cancelled the selector");
+ } else {
+ respondToClientWithErrorAndFinish(CreateCredentialException.TYPE_INTERRUPTED,
+ "The UI was interrupted - please try again.");
+ }
}
private void respondToClientWithResponseAndFinish(CreateCredentialResponse response) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
new file mode 100644
index 0000000..b7c5fc2
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/CredentialDescriptionRegistry.java
@@ -0,0 +1,125 @@
+/*
+ * 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.credentials;
+
+import android.credentials.CredentialDescription;
+import android.credentials.IRegisterCredentialDescriptionCallback;
+import android.credentials.IUnregisterCredentialDescriptionCallback;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.credentials.UnregisterCredentialDescriptionRequest;
+import android.os.RemoteException;
+import android.util.SparseArray;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/** Contains information on what CredentialProvider has what provisioned Credential. */
+public class CredentialDescriptionRegistry {
+
+ private static final int MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS = 128;
+ private static SparseArray<CredentialDescriptionRegistry> sCredentialDescriptionSessionPerUser;
+
+ static {
+ sCredentialDescriptionSessionPerUser = new SparseArray<>();
+ }
+
+ // TODO(b/265992655): add a way to update CredentialRegistry when a user is removed.
+ /** Get and/or create a {@link CredentialDescription} for the given user id. */
+ public static CredentialDescriptionRegistry forUser(int userId) {
+ CredentialDescriptionRegistry session =
+ sCredentialDescriptionSessionPerUser.get(userId, null);
+
+ if (session == null) {
+ session = new CredentialDescriptionRegistry();
+ sCredentialDescriptionSessionPerUser.put(userId, session);
+ }
+ return session;
+ }
+
+ private Map<String, Set<CredentialDescription>> mCredentialDescriptions;
+
+ private CredentialDescriptionRegistry() {
+ this.mCredentialDescriptions = new HashMap<>();
+ }
+
+ /** Handle the given {@link RegisterCredentialDescriptionRequest} by creating
+ * the appropriate package name mapping. */
+ public void executeRegisterRequest(RegisterCredentialDescriptionRequest request,
+ String callingPackageName,
+ IRegisterCredentialDescriptionCallback callback) {
+
+ if (!mCredentialDescriptions.containsKey(callingPackageName)
+ && mCredentialDescriptions.size() <= MAX_ALLOWED_CREDENTIAL_DESCRIPTIONS) {
+ mCredentialDescriptions.put(callingPackageName, new HashSet<>());
+ }
+
+ mCredentialDescriptions.get(callingPackageName)
+ .addAll(request.getCredentialDescriptions());
+
+ try {
+ callback.onResponse();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /** Handle the given {@link UnregisterCredentialDescriptionRequest} by creating
+ * the appropriate package name mapping. */
+ public void executeUnregisterRequest(
+ UnregisterCredentialDescriptionRequest request,
+ String callingPackageName,
+ IUnregisterCredentialDescriptionCallback callback) {
+
+ if (mCredentialDescriptions.containsKey(callingPackageName)) {
+ mCredentialDescriptions.get(callingPackageName)
+ .remove(request.getCredentialDescription());
+ }
+
+ try {
+ callback.onResponse();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /** Returns package names of CredentialProviders that can satisfy a given
+ * {@link CredentialDescription}. */
+ public Set<String> filterCredentials(String flatRequestString) {
+
+ Set<String> result = new HashSet<>();
+
+ for (String componentName: mCredentialDescriptions.keySet()) {
+ Set<CredentialDescription> currentSet = mCredentialDescriptions.get(componentName);
+ for (CredentialDescription containedDescription: currentSet) {
+ if (flatRequestString.equals(containedDescription.getFlattenedRequestString())) {
+ result.add(componentName);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ void evictProviderWithPackageName(String packageName) {
+ if (mCredentialDescriptions.containsKey(packageName)) {
+ mCredentialDescriptions.remove(packageName);
+ }
+ }
+
+}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index f76cf49..620b81b 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -36,14 +36,19 @@
import android.credentials.ICredentialManager;
import android.credentials.IGetCredentialCallback;
import android.credentials.IListEnabledProvidersCallback;
+import android.credentials.IRegisterCredentialDescriptionCallback;
import android.credentials.ISetEnabledProvidersCallback;
+import android.credentials.IUnregisterCredentialDescriptionCallback;
import android.credentials.ListEnabledProvidersResponse;
+import android.credentials.RegisterCredentialDescriptionRequest;
+import android.credentials.UnregisterCredentialDescriptionRequest;
import android.credentials.ui.IntentFactory;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.BeginGetCredentialRequest;
@@ -59,9 +64,13 @@
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Entry point service for credential management.
@@ -75,6 +84,8 @@
CredentialManagerService, CredentialManagerServiceImpl> {
private static final String TAG = "CredManSysService";
+ private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
+ "enable_credential_description_api";
private final Context mContext;
@@ -164,6 +175,7 @@
if (services == null) {
return;
}
+
CredentialManagerServiceImpl serviceToBeRemoved = null;
for (CredentialManagerServiceImpl service : services) {
if (service != null) {
@@ -180,10 +192,14 @@
}
if (serviceToBeRemoved != null) {
removeServiceFromCache(serviceToBeRemoved, userId);
+ CredentialDescriptionRegistry.forUser(userId)
+ .evictProviderWithPackageName(serviceToBeRemoved.getServicePackageName());
}
// TODO("Iterate over system services and remove if needed")
}
+
+
@GuardedBy("mLock")
private List<CredentialManagerServiceImpl> getOrConstructSystemServiceListLock(
int resolvedUserId) {
@@ -223,6 +239,53 @@
concatenatedServices.addAll(getOrConstructSystemServiceListLock(userId));
return concatenatedServices;
}
+ public static boolean isCredentialDescriptionApiEnabled() {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+ }
+
+ @SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
+ // to be guarded by 'service.mLock', which is the same as mLock.
+ private List<ProviderSession> initiateProviderSessionsWithActiveContainers(
+ RequestSession session,
+ List<String> requestOptions, Set<ComponentName> activeCredentialContainers) {
+ List<ProviderSession> providerSessions = new ArrayList<>();
+ // Invoke all services of a user to initiate a provider session
+ runForUser((service) -> {
+ if (activeCredentialContainers.contains(service.getComponentName())) {
+ ProviderSession providerSession = service
+ .initiateProviderSessionForRequestLocked(session, requestOptions);
+ if (providerSession != null) {
+ providerSessions.add(providerSession);
+ }
+ }
+ });
+ return providerSessions;
+ }
+
+ @NonNull
+ private Set<String> getMatchingProviders(GetCredentialRequest request) {
+ // Session for active/provisioned credential descriptions;
+ CredentialDescriptionRegistry registry = CredentialDescriptionRegistry
+ .forUser(UserHandle.getCallingUserId());
+
+ // All requested credential descriptions based on the given request.
+ Set<String> requestedCredentialDescriptions =
+ request.getGetCredentialOptions().stream().map(
+ getCredentialOption -> getCredentialOption
+ .getCredentialRetrievalData()
+ .getString(RegisterCredentialDescriptionRequest
+ .FLATTENED_REQUEST_STRING_KEY))
+ .collect(Collectors.toSet());
+
+ // All requested credential descriptions based on the given request.
+ return requestedCredentialDescriptions.stream()
+ .map(registry::filterCredentials)
+ .flatMap(
+ (Function<Set<String>, Stream<String>>)
+ Collection::stream)
+ .collect(Collectors.toSet());
+ }
@SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
// to be guarded by 'service.mLock', which is the same as mLock.
@@ -282,11 +345,11 @@
// Initiate all provider sessions
List<ProviderSession> providerSessions =
- initiateProviderSessions(
- session,
- request.getGetCredentialOptions().stream()
- .map(GetCredentialOption::getType)
- .collect(Collectors.toList()));
+ initiateProviderSessions(
+ session,
+ request.getGetCredentialOptions().stream()
+ .map(GetCredentialOption::getType)
+ .collect(Collectors.toList()));
if (providerSessions.isEmpty()) {
try {
@@ -316,7 +379,7 @@
ICreateCredentialCallback callback,
String callingPackage) {
Log.i(TAG, "starting executeCreateCredential with callingPackage: " + callingPackage);
- // TODO : Implement cancellation
+
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
// New request session, scoped for this request only.
@@ -478,5 +541,77 @@
});
return cancelTransport;
}
+
+ @Override
+ public ICancellationSignal registerCredentialDescription(
+ RegisterCredentialDescriptionRequest request,
+ IRegisterCredentialDescriptionCallback callback, String callingPackage) {
+ Log.i(TAG, "registerCredentialDescription");
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+
+
+ List<CredentialProviderInfo> services =
+ CredentialProviderInfo.getAvailableServices(mContext,
+ UserHandle.getCallingUserId());
+
+ List<String> providers = services.stream()
+ .map(credentialProviderInfo
+ -> credentialProviderInfo.getServiceInfo().packageName).toList();
+ if (!providers.contains(callingPackage)) {
+ try {
+ callback.onError("UNKNOWN",
+ "Not an existing provider.");
+ } catch (RemoteException e) {
+ Log.i(
+ TAG,
+ "Issue invoking onError on IRegisterCredentialDescriptionCallback "
+ + "callback: "
+ + e.getMessage());
+ }
+ }
+
+ CredentialDescriptionRegistry session = CredentialDescriptionRegistry
+ .forUser(UserHandle.getCallingUserId());
+
+ session.executeRegisterRequest(request, callingPackage, callback);
+
+ return cancelTransport;
+ }
+
+ @Override
+ public ICancellationSignal unRegisterCredentialDescription(
+ UnregisterCredentialDescriptionRequest request,
+ IUnregisterCredentialDescriptionCallback callback, String callingPackage) {
+ Log.i(TAG, "registerCredentialDescription");
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+
+ List<CredentialProviderInfo> services =
+ CredentialProviderInfo.getAvailableServices(mContext,
+ UserHandle.getCallingUserId());
+
+ List<String> providers = services.stream()
+ .map(credentialProviderInfo
+ -> credentialProviderInfo.getServiceInfo().packageName).toList();
+
+ if (!providers.contains(callingPackage)) {
+ try {
+ callback.onError("UNKNOWN",
+ "Not an existing provider.");
+ } catch (RemoteException e) {
+ Log.i(
+ TAG,
+ "Issue invoking onError on IRegisterCredentialDescriptionCallback "
+ + "callback: "
+ + e.getMessage());
+ }
+ }
+
+ CredentialDescriptionRegistry session = CredentialDescriptionRegistry
+ .forUser(UserHandle.getCallingUserId());
+
+ session.executeUnregisterRequest(request, callingPackage, callback);
+
+ return cancelTransport;
+ }
}
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
index a380636..797601a 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
@@ -64,8 +64,11 @@
} else {
Slog.i(TAG, "No selection found in UI result");
}
- } else if (resultCode == UserSelectionDialogResult.RESULT_CODE_DIALOG_CANCELED) {
- mCallbacks.onUiCancellation();
+ } else if (resultCode == UserSelectionDialogResult.RESULT_CODE_DIALOG_USER_CANCELED) {
+ mCallbacks.onUiCancellation(/* isUserCancellation= */ true);
+ } else if (resultCode
+ == UserSelectionDialogResult.RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS) {
+ mCallbacks.onUiCancellation(/* isUserCancellation= */ false);
}
}
@@ -75,8 +78,8 @@
public interface CredentialManagerUiCallback {
/** Called when the user makes a selection. */
void onUiSelection(UserSelectionDialogResult selection);
- /** Called when the user cancels the UI. */
- void onUiCancellation();
+ /** Called when the UI is canceled without a successful provider result. */
+ void onUiCancellation(boolean isUserCancellation);
}
public CredentialManagerUi(Context context, int userId,
CredentialManagerUiCallback callbacks) {
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index f7c5905..e3a27ec 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -124,9 +124,14 @@
}
@Override
- public void onUiCancellation() {
- respondToClientWithErrorAndFinish(GetCredentialException.TYPE_USER_CANCELED,
- "User cancelled the selector");
+ public void onUiCancellation(boolean isUserCancellation) {
+ if (isUserCancellation) {
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_USER_CANCELED,
+ "User cancelled the selector");
+ } else {
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_INTERRUPTED,
+ "The UI was interrupted - please try again.");
+ }
}
@Override
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index 8e44f0f..f92ffe2 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -125,8 +125,8 @@
}
@Override // from CredentialManagerUiCallbacks
- public void onUiCancellation() {
- Log.i(TAG, "Ui canceled");
+ public void onUiCancellation(boolean isUserCancellation) {
+ Log.i(TAG, "Ui canceled. Canceled by user: " + isUserCancellation);
// User canceled the activity
finishSession();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ce67f3c..1406a396 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -30,6 +30,7 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY;
+import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
@@ -105,6 +106,7 @@
import static android.app.admin.DevicePolicyManager.STATUS_DEVICE_ADMIN_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_HAS_DEVICE_OWNER;
import static android.app.admin.DevicePolicyManager.STATUS_HAS_PAIRED;
+import static android.app.admin.DevicePolicyManager.STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_MANAGED_USERS_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_NONSYSTEM_USER_EXISTS;
import static android.app.admin.DevicePolicyManager.STATUS_NOT_SYSTEM_USER;
@@ -140,6 +142,7 @@
import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED;
import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.GET_META_DATA;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -2929,7 +2932,7 @@
final ActivityInfo ai = mInjector.binderWithCleanCallingIdentity(() -> {
try {
return mIPackageManager.getReceiverInfo(adminName,
- PackageManager.GET_META_DATA
+ GET_META_DATA
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
@@ -7957,13 +7960,11 @@
Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userId));
synchronized (getLockObject()) {
- if (mOwners.hasProfileOwner(userId) || mOwners.hasDeviceOwner()) {
- final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
- return admin.mNearbyNotificationStreamingPolicy;
- }
+ final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
+ return admin != null
+ ? admin.mNearbyNotificationStreamingPolicy
+ : NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
-
- return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
@Override
@@ -7998,13 +7999,11 @@
Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userId));
synchronized (getLockObject()) {
- if (mOwners.hasProfileOwner(userId) || mOwners.hasDeviceOwner()) {
- final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
- return admin.mNearbyAppStreamingPolicy;
- }
+ final ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userId);
+ return admin != null
+ ? admin.mNearbyAppStreamingPolicy
+ : NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
-
- return NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
}
/**
@@ -14758,7 +14757,14 @@
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
- return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId());
+ long originalId = mInjector.binderClearCallingIdentity();
+ try {
+ return checkProvisioningPreconditionSkipPermission(
+ action, packageName, caller.getUserId());
+ } finally {
+ mInjector.binderRestoreCallingIdentity(originalId);
+ }
+
}
private int checkProvisioningPreconditionSkipPermission(String action,
String packageName, int userId) {
@@ -14824,22 +14830,31 @@
return STATUS_USER_HAS_PROFILE_OWNER;
}
- boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
- // System user is always running in headless system user mode.
- if (!isHeadlessSystemUserMode
- && !mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
+ if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
return STATUS_USER_NOT_RUNNING;
}
if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
return STATUS_HAS_PAIRED;
}
+ boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
+
if (isHeadlessSystemUserMode) {
if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
Slogf.e(LOG_TAG, "In headless system user mode, "
+ "device owner can only be set on headless system user.");
return STATUS_NOT_SYSTEM_USER;
}
+
+ if (owner != null) {
+ DeviceAdminInfo adminInfo = findAdmin(
+ owner, deviceOwnerUserId, /* throwForMissingPermission= */ false);
+
+ if (adminInfo.getHeadlessDeviceOwnerMode()
+ != HEADLESS_DEVICE_OWNER_MODE_AFFILIATED) {
+ return STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED;
+ }
+ }
}
if (isAdb) {
@@ -18971,11 +18986,12 @@
"Provisioning preconditions failed with result: " + result);
}
onProvisionFullyManagedDeviceStarted(provisioningParams);
+
+ // These properties are global so will apply on all users
setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime());
setLocale(provisioningParams.getLocale());
- final int deviceOwnerUserId = mInjector.userManagerIsHeadlessSystemUserMode()
- ? UserHandle.USER_SYSTEM : caller.getUserId();
+ int deviceOwnerUserId = UserHandle.USER_SYSTEM;
if (!removeNonRequiredAppsForManagedDevice(
deviceOwnerUserId,
provisioningParams.isLeaveAllSystemAppsEnabled(),
@@ -19101,9 +19117,12 @@
}
private void disallowAddUser() {
- if (mInjector.userManagerIsHeadlessSystemUserMode()) {
- Slogf.i(LOG_TAG, "Not setting DISALLOW_ADD_USER on headless system user mode.");
- return;
+ if (!isHeadlessFlagEnabled() || mIsAutomotive) {
+ // Auto still enables adding users due to the communal nature of those devices
+ if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+ Slogf.i(LOG_TAG, "Not setting DISALLOW_ADD_USER on headless system user mode.");
+ return;
+ }
}
for (UserInfo userInfo : mUserManager.getUsers()) {
UserHandle userHandle = userInfo.getUserHandle();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5c5442d..3725756 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2736,6 +2736,10 @@
mSystemServiceManager.startService(PermissionPolicyService.class);
t.traceEnd();
+ t.traceBegin("ArtManagerLocal");
+ DexOptHelper.initializeArtManagerLocal(context, mPackageManagerService);
+ t.traceEnd();
+
t.traceBegin("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
t.traceEnd();
@@ -2770,10 +2774,6 @@
mSystemServiceManager.startService(GAME_MANAGER_SERVICE_CLASS);
t.traceEnd();
- t.traceBegin("ArtManagerLocal");
- DexOptHelper.initializeArtManagerLocal(context, mPackageManagerService);
- t.traceEnd();
-
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
t.traceBegin("UwbService");
mSystemServiceManager.startServiceFromJar(UWB_SERVICE_CLASS, UWB_APEX_SERVICE_JAR_PATH);
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index ae8dd41..0ca4dfc 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -1162,9 +1162,9 @@
private final int mUserId;
- // Conversation package name + shortcut ID -> Number of active notifications
+ // Conversation package name + shortcut ID -> Keys of active notifications
@GuardedBy("this")
- private final Map<Pair<String, String>, Integer> mActiveNotifCounts = new ArrayMap<>();
+ private final Map<Pair<String, String>, Set<String>> mActiveNotifKeys = new ArrayMap<>();
private NotificationListener(int userId) {
mUserId = userId;
@@ -1178,8 +1178,10 @@
String shortcutId = sbn.getNotification().getShortcutId();
PackageData packageData = getPackageIfConversationExists(sbn, conversationInfo -> {
synchronized (this) {
- mActiveNotifCounts.merge(
- Pair.create(sbn.getPackageName(), shortcutId), 1, Integer::sum);
+ Set<String> notificationKeys = mActiveNotifKeys.computeIfAbsent(
+ Pair.create(sbn.getPackageName(), shortcutId),
+ (unusedKey) -> new HashSet<>());
+ notificationKeys.add(sbn.getKey());
}
});
@@ -1218,12 +1220,12 @@
Pair<String, String> conversationKey =
Pair.create(sbn.getPackageName(), shortcutId);
synchronized (this) {
- int count = mActiveNotifCounts.getOrDefault(conversationKey, 0) - 1;
- if (count <= 0) {
- mActiveNotifCounts.remove(conversationKey);
+ Set<String> notificationKeys = mActiveNotifKeys.computeIfAbsent(
+ conversationKey, (unusedKey) -> new HashSet<>());
+ notificationKeys.remove(sbn.getKey());
+ if (notificationKeys.isEmpty()) {
+ mActiveNotifKeys.remove(conversationKey);
cleanupCachedShortcuts(mUserId, MAX_CACHED_RECENT_SHORTCUTS);
- } else {
- mActiveNotifCounts.put(conversationKey, count);
}
}
});
@@ -1289,7 +1291,7 @@
}
synchronized boolean hasActiveNotifications(String packageName, String shortcutId) {
- return mActiveNotifCounts.containsKey(Pair.create(packageName, shortcutId));
+ return mActiveNotifKeys.containsKey(Pair.create(packageName, shortcutId));
}
}
diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
index 694efbb..730cac9 100644
--- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt
@@ -440,7 +440,8 @@
Log.w(
LOG_TAG, "Ignoring permission $permissionName declared in system package" +
" $newPackageName: already declared in another system package" +
- " $oldPackageName")
+ " $oldPackageName"
+ )
return@forEachIndexed
}
} else {
@@ -516,15 +517,20 @@
if (packageState != null && androidPackage == null) {
return
}
- // TODO: STOPSHIP: We may need to retain permission definitions by disabled system packages
- // to retain their permission state.
-
+ val disabledSystemPackage = systemState.disabledSystemPackageStates[packageName]
+ ?.androidPackage
+ // Unlike in the previous implementation, we now also retain permission trees defined by
+ // disabled system packages for consistency with permissions.
val isPermissionTreeRemoved = systemState.permissionTrees.removeAllIndexed {
_, permissionTreeName, permissionTree ->
permissionTree.packageName == packageName && (
packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
it.isTree && it.name == permissionTreeName
}
+ ) && (
+ disabledSystemPackage?.permissions?.anyIndexed { _, it ->
+ it.isTree && it.name == permissionTreeName
+ } != true
)
}
if (isPermissionTreeRemoved) {
@@ -538,6 +544,10 @@
packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
!it.isTree && it.name == permissionName
}
+ ) && (
+ disabledSystemPackage?.permissions?.anyIndexed { _, it ->
+ !it.isTree && it.name == permissionName
+ } != true
)) {
// Different from the old implementation where we keep the permission state if the
// permission is declared by a disabled system package (ag/15189282), we now
@@ -574,8 +584,14 @@
private fun MutateStateScope.trimPermissionStates(appId: Int) {
val requestedPermissions = IndexedSet<String>()
forEachPackageInAppId(appId) {
+ // Note that we still trim the permission states requested by disabled system packages.
+ // Because in the previous implementation:
+ // despite revokeSharedUserPermissionsForLeavingPackageInternal() retains permissions
+ // requested by disabled system packages, revokeUnusedSharedUserPermissionsLocked(),
+ // which is call upon app update installation, didn't do such preservation.
+ // Hence, permissions only requested by disabled system packages were still trimmed in
+ // the previous implementation.
requestedPermissions += it.androidPackage!!.requestedPermissions
- // TODO: STOPSHIP: Retain permissions requested by disabled system packages.
}
newState.userStates.forEachIndexed { _, userId, userState ->
userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 70a5c3f..05a8b11 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -28,7 +28,7 @@
],
srcs: [
- "src/server/**/*.java",
+ "src/com/android/server/inputmethod/**/*.java",
],
static_libs: [
diff --git a/services/tests/InputMethodSystemServerTests/TEST_MAPPING b/services/tests/InputMethodSystemServerTests/TEST_MAPPING
new file mode 100644
index 0000000..77e32a7
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksInputMethodSystemServerTests",
+ "options": [
+ {"include-filter": "com.android.server.inputmethod"},
+ {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {"exclude-annotation": "org.junit.Ignore"}
+ ]
+ }
+ ]
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 73d04c6..720f486 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -65,19 +65,24 @@
@Test
public void testPerformShowIme() throws Exception {
- mVisibilityApplier.performShowIme(mWindowToken, null, null, SHOW_SOFT_INPUT);
+ synchronized (ImfLock.class) {
+ mVisibilityApplier.performShowIme(mWindowToken, null /* statsToken */,
+ InputMethodManager.SHOW_IMPLICIT, null, SHOW_SOFT_INPUT);
+ }
verifyShowSoftInput(false, true, InputMethodManager.SHOW_IMPLICIT);
}
@Test
public void testPerformHideIme() throws Exception {
- mVisibilityApplier.performHideIme(mWindowToken, null, null, HIDE_SOFT_INPUT);
+ synchronized (ImfLock.class) {
+ mVisibilityApplier.performHideIme(mWindowToken, null /* statsToken */, null,
+ HIDE_SOFT_INPUT);
+ }
verifyHideSoftInput(false, true);
}
@Test
public void testApplyImeVisibility_throwForInvalidState() {
- mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID);
assertThrows(IllegalArgumentException.class,
() -> mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_INVALID));
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
index 8415fe1..a1b9b98 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -30,6 +30,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.inputmethod.InputMethodManager;
@@ -177,9 +178,28 @@
assertThat(state.getImeDisplayId()).isEqualTo(FALLBACK_DISPLAY_ID);
}
- private void initImeTargetWindowState(IBinder windowToken) {
+ @Test
+ public void testComputeState_lastImeRequestedVisible_preserved_When_StateUnChanged() {
+ // Assume the last IME targeted window has requested IME visible
+ final IBinder lastImeTargetWindowToken = new Binder();
+ mInputMethodManagerService.mLastImeTargetWindow = lastImeTargetWindowToken;
+ mComputer.requestImeVisibility(lastImeTargetWindowToken, true);
+ final ImeTargetWindowState lastState = mComputer.getWindowStateOrNull(
+ lastImeTargetWindowToken);
+ assertThat(lastState.isRequestedImeVisible()).isTrue();
+
+ // Verify when focusing the next window with STATE_UNCHANGED flag, the last IME
+ // visibility state will be preserved to the current window state.
+ final ImeTargetWindowState stateWithUnChangedFlag = initImeTargetWindowState(mWindowToken);
+ mComputer.computeState(stateWithUnChangedFlag, true /* allowVisible */);
+ assertThat(stateWithUnChangedFlag.isRequestedImeVisible()).isEqualTo(
+ lastState.isRequestedImeVisible());
+ }
+
+ private ImeTargetWindowState initImeTargetWindowState(IBinder windowToken) {
final ImeTargetWindowState state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNCHANGED,
0, true, true, true);
mComputer.setWindowState(windowToken, state);
+ return state;
}
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 804bb49..dbdffd0 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -71,6 +71,8 @@
/** Base class for testing {@link InputMethodManagerService}. */
public class InputMethodManagerServiceTestBase {
+ private static final int NO_VERIFY_SHOW_FLAGS = -1;
+
protected static final String TEST_SELECTED_IME_ID = "test.ime";
protected static final String TEST_EDITOR_PKG_NAME = "test.editor";
protected static final String TEST_FOCUSED_WINDOW_NAME = "test.editor/activity";
@@ -239,7 +241,7 @@
protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
throws RemoteException {
- verifyShowSoftInput(setVisible, showSoftInput, anyInt());
+ verifyShowSoftInput(setVisible, showSoftInput, NO_VERIFY_SHOW_FLAGS);
}
protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput, int showFlags)
@@ -249,7 +251,8 @@
.setCurrentMethodVisible();
}
verify(mMockInputMethod, times(showSoftInput ? 1 : 0))
- .showSoftInput(any(), any(), eq(showFlags), any());
+ .showSoftInput(any(), any(),
+ showFlags != NO_VERIFY_SHOW_FLAGS ? eq(showFlags) : anyInt(), any());
}
protected void verifyHideSoftInput(boolean setNotVisible, boolean hideSoftInput)
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp
new file mode 100644
index 0000000..69b26cc
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/Android.bp
@@ -0,0 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "FrameworksServicesTests_install_target_sdk_22",
+ defaults: ["FrameworksServicesTests_apks_defaults"],
+
+ srcs: ["**/*.java"],
+}
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml
new file mode 100644
index 0000000..45cf769
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.install_target_sdk_22">
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="22">
+ </uses-sdk>
+
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml
new file mode 100644
index 0000000..984152f
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_22/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this placeholder file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="placeholder">placeholder</string>
+</resources>
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp
new file mode 100644
index 0000000..e3154db
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/Android.bp
@@ -0,0 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "FrameworksServicesTests_install_target_sdk_23",
+ defaults: ["FrameworksServicesTests_apks_defaults"],
+
+ srcs: ["**/*.java"],
+}
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml
new file mode 100644
index 0000000..725188b
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.install_target_sdk_23">
+ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="23">
+ </uses-sdk>
+
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml
new file mode 100644
index 0000000..984152f
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/apks/install_target_sdk_23/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this placeholder file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="placeholder">placeholder</string>
+</resources>
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index ebd6b64..f7efcd1 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -146,6 +146,8 @@
":FrameworksServicesTests_keyset_sb_ub",
":FrameworksServicesTests_keyset_splat_api",
":FrameworksServicesTests_keyset_splata_api",
+ ":FrameworksServicesTests_install_target_sdk_22",
+ ":FrameworksServicesTests_install_target_sdk_23",
],
out: ["PackageManagerServiceServerTests_apks_as_resources.res.zip"],
tools: ["soong_zip"],
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
index 92bdd64..fd31b22 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerTests.java
@@ -57,6 +57,7 @@
import android.os.StatFs;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.system.ErrnoException;
@@ -69,11 +70,10 @@
import androidx.test.filters.SmallTest;
import androidx.test.filters.Suppress;
-import com.android.server.pm.test.service.server.R;
import com.android.internal.content.InstallLocationUtils;
import com.android.server.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.pkg.parsing.ParsingPackage;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+import com.android.server.pm.test.service.server.R;
import dalvik.system.VMRuntime;
@@ -113,6 +113,9 @@
private static final int APP_INSTALL_SDCARD = InstallLocationUtils.APP_INSTALL_EXTERNAL;
+ private static final int DEFAULT_INSTALL_FLAGS =
+ PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+
void failStr(String errMsg) {
Log.w(TAG, "errMsg=" + errMsg);
fail(errMsg);
@@ -1874,12 +1877,13 @@
private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail,
int retCode) throws Exception {
- int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+ int rFlags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
var pkg1 = getParsedPackage(apk1Name, apk1);
try {
- InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
+ InstallParams ip = installFromRawResource(apk1Name, apk1,
+ DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
installFromRawResource(apk2Name, apk2, rFlags, false,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
@@ -1963,7 +1967,7 @@
InstallParams ip = replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, false, true,
PackageInstaller.STATUS_FAILURE_CONFLICT);
try {
- int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+ int rFlags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
installFromRawResource("install.apk", APP1_CERT1, rFlags, false,
false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
@@ -2466,7 +2470,8 @@
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
- final InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
+ final InstallParams ip = installFromRawResource(apk1Name, apk1,
+ DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
try {
PackageManager pm = mContext.getPackageManager();
@@ -2552,13 +2557,13 @@
// Clean up before testing first.
cleanUpInstall(pkg1.getPackageName());
cleanUpInstall(pkg2.getPackageName());
- installFromRawResource(apk1Name, apk1, 0, false, false, -1,
+ installFromRawResource(apk1Name, apk1, DEFAULT_INSTALL_FLAGS, false, false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
if (fail) {
- installFromRawResource(apk2Name, apk2, 0, false, true, retCode,
+ installFromRawResource(apk2Name, apk2, DEFAULT_INSTALL_FLAGS, false, true, retCode,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
} else {
- installFromRawResource(apk2Name, apk2, 0, false, false, -1,
+ installFromRawResource(apk2Name, apk2, DEFAULT_INSTALL_FLAGS, false, false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
// TODO: All checkSignatures tests should return the same result regardless of
// querying by package name or uid; however if there are any edge cases where
@@ -2638,7 +2643,7 @@
InstallParams ip1 = null;
try {
- ip1 = installFromRawResource(apk1Name, apk1, 0, false,
+ ip1 = installFromRawResource(apk1Name, apk1, DEFAULT_INSTALL_FLAGS, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
PackageManager pm = mContext.getPackageManager();
// Delete app2
@@ -2683,9 +2688,10 @@
int apk2 = SHARED2_CERT1_CERT2;
int rapk1 = SHARED1_CERT1;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2695,9 +2701,10 @@
int apk2 = SHARED2_CERT1_CERT2;
int rapk2 = SHARED2_CERT1;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2707,9 +2714,10 @@
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2719,9 +2727,10 @@
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2731,9 +2740,10 @@
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk1, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2743,9 +2753,10 @@
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT1_CERT2;
boolean fail = true;
+ int flags = DEFAULT_INSTALL_FLAGS | PackageManager.INSTALL_REPLACE_EXISTING;
int retCode = PackageInstaller.STATUS_FAILURE_CONFLICT;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
- installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
+ installFromRawResource("install.apk", rapk2, flags, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
@@ -2995,6 +3006,58 @@
getPm().registerDexModule(nonExistentApk, null);
}
+ @LargeTest
+ public void testMinInstallableTargetSdkPass() throws Exception {
+ // Test installing a package that meets the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+ installFromRawResource("install.apk", R.raw.install_target_sdk_23, flags,
+ true, false /* fail */, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ @LargeTest
+ public void testMinInstallableTargetSdkFail() throws Exception {
+ // Test installing a package that doesn't meet the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = 0;
+ // Expect install to fail
+ installFromRawResource("install.apk", R.raw.install_target_sdk_22, flags,
+ true, true /* fail */, PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ @LargeTest
+ public void testMinInstallableTargetSdkBypass() throws Exception {
+ // Test installing a package that doesn't meet the minimum installable sdk requirement
+ setMinInstallableTargetSdkFeatureFlags();
+ int flags = PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
+ installFromRawResource("install.apk", R.raw.install_target_sdk_22, flags,
+ true, false /* fail */, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ }
+
+ private void setMinInstallableTargetSdkFeatureFlags() {
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__install_block_enabled",
+ "true",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__min_installable_target_sdk",
+ "23",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__install_block_strict_mode_enabled",
+ "true",
+ false);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ "MinInstallableTargetSdk__strict_mode_target_sdk",
+ "23",
+ false);
+ }
+
// Copied from com.android.server.pm.InstructionSets because we don't have access to it here.
private static String[] getAppDexInstructionSets(ApplicationInfo info) {
if (info.primaryCpuAbi != null) {
diff --git a/services/tests/mockingservicestests/OWNERS b/services/tests/mockingservicestests/OWNERS
index 4dda51f..0640d52 100644
--- a/services/tests/mockingservicestests/OWNERS
+++ b/services/tests/mockingservicestests/OWNERS
@@ -6,3 +6,6 @@
per-file FakeServiceConnector.java = file:/GAME_MANAGER_OWNERS
per-file Game* = file:/GAME_MANAGER_OWNERS
per-file res/xml/game_manager* = file:/GAME_MANAGER_OWNERS
+
+# General utilities
+per-file services/tests/mockingservicestests/src/com/android/server/*.java=felipeal@google.com
diff --git a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
index 33275bd..a0687f6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DumpableDumperRule.java
@@ -62,14 +62,21 @@
};
}
- private void dumpOnFailure(String testName) throws IOException {
+ /**
+ * Logs all dumpables.
+ */
+ public void dump(String reason) {
if (mDumpables.isEmpty()) {
return;
}
- Log.w(TAG, "Dumping " + mDumpables.size() + " dumpables on failure of " + testName);
+ Log.w(TAG, "Dumping " + mDumpables.size() + " dumpable(s). Reason: " + reason);
mDumpables.forEach(d -> logDumpable(d));
}
+ private void dumpOnFailure(String testName) throws IOException {
+ dump("failure of " + testName);
+ }
+
private void logDumpable(Dumpable dumpable) {
try {
try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index 5f4ff1a..45fe795 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -1191,31 +1191,6 @@
}
/**
- * Verify that we detect and ANR a wedged process when delivering a
- * broadcast with more than one priority tranche.
- */
- @Test
- public void testWedged_Registered_Prioritized() throws Exception {
- // Legacy stack doesn't detect these ANRs; likely an oversight
- Assume.assumeTrue(mImpl == Impl.MODERN);
-
- final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
- final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN,
- ProcessBehavior.WEDGE);
- final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE,
- ProcessBehavior.NORMAL);
-
- final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- enqueueBroadcast(makeBroadcastRecord(airplane, callerApp,
- List.of(makeRegisteredReceiver(receiverGreenApp, 10),
- makeRegisteredReceiver(receiverBlueApp, 5))));
-
- waitForIdle();
- verify(mAms).appNotResponding(eq(receiverGreenApp), any());
- verifyScheduleRegisteredReceiver(receiverBlueApp, airplane);
- }
-
- /**
* Verify that we handle registered receivers in a process that always
* responds with {@link DeadObjectException}, recovering to restart the
* process and deliver their next broadcast.
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
index 3f16a98..3deb903 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
@@ -1048,8 +1048,7 @@
Consumer<Uri> consumer = invocation.getArgument(invocation.getArguments().length - 1);
consumer.accept(Uri.parse("a/b.png"));
return null;
- }).when(mMockScreenshotHelper).provideScreenshot(
- any(), any(), any(), anyInt(), anyInt(), any(), anyInt(), any(), any());
+ }).when(mMockScreenshotHelper).takeScreenshot(any(), any(), any());
mGameServiceProviderInstance.start();
startTask(taskId, GAME_A_MAIN_ACTIVITY);
mFakeGameService.requestCreateGameSession(taskId);
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 2a790a1..f2cba40 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -80,8 +80,6 @@
@Mock
private DisplayBlanker mDisplayBlankerMock;
@Mock
- private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
- @Mock
private LogicalDisplay mLogicalDisplayMock;
@Mock
private DisplayDevice mDisplayDeviceMock;
@@ -171,7 +169,7 @@
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
- }, mHighBrightnessModeMetadataMock);
+ });
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index d99ed78..4f8cb88 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -84,8 +84,6 @@
@Mock
private DisplayDevice mDisplayDeviceMock;
@Mock
- private HighBrightnessModeMetadata mHighBrightnessModeMetadataMock;
- @Mock
private BrightnessTracker mBrightnessTrackerMock;
@Mock
private BrightnessSetting mBrightnessSettingMock;
@@ -153,7 +151,7 @@
mContextSpy, mInjector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, mLogicalDisplayMock,
mBrightnessTrackerMock, mBrightnessSettingMock, () -> {
- }, mHighBrightnessModeMetadataMock);
+ });
when(mDisplayPowerStateMock.getScreenState()).thenReturn(Display.STATE_ON);
// send a display power request
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
index 7e1a42b..ddb6f23 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
@@ -30,6 +30,7 @@
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_FGS;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
+import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_UI;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -855,6 +856,9 @@
case WORK_TYPE_FGS:
workTypeString = "fgs";
break;
+ case WORK_TYPE_UI:
+ workTypeString = "ui";
+ break;
case WORK_TYPE_EJ:
workTypeString = "ej";
break;
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
index 579621c..36c9f2e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUMDTest.java
@@ -15,6 +15,8 @@
*/
package com.android.server.pm;
+import org.junit.Test;
+
/**
* Tests for {@link UserVisibilityMediator} tests for devices that support concurrent Multiple
* Users on Multiple Displays (A.K.A {@code MUMD}).
@@ -26,6 +28,19 @@
extends UserVisibilityMediatorVisibleBackgroundUserTestCase {
public UserVisibilityMediatorMUMDTest() throws Exception {
- super(/* usersOnSecondaryDisplaysEnabled= */ true);
+ super(/* backgroundUsersOnDisplaysEnabled= */ true,
+ /* backgroundUserOnDefaultDisplayAllowed= */ false);
+ }
+
+ @Test
+ public void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
+ int userId = visibleBgUserCannotBeStartedOnDefaultDisplayTest();
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(userId, SECONDARY_DISPLAY_ID);
+ }
+
+ @Test
+ public void testStartBgUser_onDefaultDisplay_visible() throws Exception {
+ visibleBgUserCannotBeStartedOnDefaultDisplayTest();
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
new file mode 100644
index 0000000..01ce696
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorMUPANDTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.pm;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
+import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
+import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
+import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
+import static com.android.server.pm.UserVisibilityMediator.INITIAL_CURRENT_USER_ID;
+
+import org.junit.Test;
+
+/**
+ * Tests for {@link UserVisibilityMediator} tests for devices that support not only concurrent
+ * Multiple Users on Multiple Displays, but also let background users to be visible in the default
+ * display (A.K.A {@code MUPAND} - MUltiple Passengers, No Driver).
+ *
+ * <p> Run as {@code
+* atest FrameworksMockingServicesTests:com.android.server.pm.UserVisibilityMediatorMUPANDTest}
+ */
+public final class UserVisibilityMediatorMUPANDTest
+ extends UserVisibilityMediatorVisibleBackgroundUserTestCase {
+
+ public UserVisibilityMediatorMUPANDTest() throws Exception {
+ super(/* backgroundUsersOnDisplaysEnabled= */ true,
+ /* backgroundUserOnDefaultDisplayAllowed= */ true);
+ }
+
+ @Test
+ public void testStartVisibleBgUser_onDefaultDisplay_initialCurrentUserId()
+ throws Exception {
+ int currentUserId = INITIAL_CURRENT_USER_ID;
+ int visibleBgUserId = USER_ID;
+ int otherUserId = OTHER_USER_ID;
+
+ AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(visibleBgUserId));
+
+ int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectVisibleUsers(currentUserId, visibleBgUserId);
+
+ // Assert bg user visibility
+ expectUserIsVisible(visibleBgUserId);
+ expectUserIsVisibleOnDisplay(visibleBgUserId, DEFAULT_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(visibleBgUserId, INVALID_DISPLAY);
+ expectDisplayAssignedToUser(visibleBgUserId, DEFAULT_DISPLAY);
+ expectUserAssignedToDisplay(DEFAULT_DISPLAY, visibleBgUserId);
+
+ // Assert current user visibility
+ expectUserIsVisible(currentUserId);
+ expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
+ expectDisplayAssignedToUser(currentUserId, INVALID_DISPLAY);
+
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ // Make sure another user cannot be started on default display
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
+ "when user (%d) is starting on default display after it was started by user %d",
+ otherUserId, visibleBgUserId);
+ expectVisibleUsers(currentUserId, visibleBgUserId);
+
+ listener.verify();
+ }
+
+ @Test
+ public void testStartVisibleBgUser_onDefaultDisplay_nonInitialCurrentUserId()
+ throws Exception {
+ int currentUserId = OTHER_USER_ID;
+ int visibleBgUserId = USER_ID;
+ int otherUserId = YET_ANOTHER_USER_ID;
+
+ AsyncUserVisibilityListener listener = addListenerForEvents(
+ onInvisible(INITIAL_CURRENT_USER_ID),
+ onVisible(currentUserId),
+ onVisible(visibleBgUserId));
+ startForegroundUser(currentUserId);
+
+ int result = mMediator.assignUserToDisplayOnStart(visibleBgUserId, visibleBgUserId,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
+ expectVisibleUsers(currentUserId, visibleBgUserId);
+
+ // Assert bg user visibility
+ expectUserIsVisible(visibleBgUserId);
+ expectUserIsVisibleOnDisplay(visibleBgUserId, DEFAULT_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(visibleBgUserId, INVALID_DISPLAY);
+ expectDisplayAssignedToUser(visibleBgUserId, DEFAULT_DISPLAY);
+ expectUserAssignedToDisplay(DEFAULT_DISPLAY, visibleBgUserId);
+
+ // Assert current user visibility
+ expectUserIsVisible(currentUserId);
+ expectUserIsVisibleOnDisplay(currentUserId, DEFAULT_DISPLAY);
+ expectUserIsNotVisibleOnDisplay(currentUserId, INVALID_DISPLAY);
+ expectDisplayAssignedToUser(currentUserId, INVALID_DISPLAY);
+
+ assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
+
+ // Make sure another user cannot be started on default display
+ int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
+ BG_VISIBLE, DEFAULT_DISPLAY);
+ assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
+ "when user (%d) is starting on default display after it was started by user %d",
+ otherUserId, visibleBgUserId);
+ expectVisibleUsers(currentUserId, visibleBgUserId);
+
+ listener.verify();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
index b9ba780..c195064 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorSUSDTest.java
@@ -37,7 +37,15 @@
public final class UserVisibilityMediatorSUSDTest extends UserVisibilityMediatorTestCase {
public UserVisibilityMediatorSUSDTest() {
- super(/* usersOnSecondaryDisplaysEnabled= */ false);
+ super(/* backgroundUsersOnDisplaysEnabled= */ false,
+ /* backgroundUserOnDefaultDisplayAllowed= */ false);
+ }
+
+ @Test
+ public void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
+ int userId = visibleBgUserCannotBeStartedOnDefaultDisplayTest();
+
+ assertInvisibleUserCannotBeAssignedExtraDisplay(userId, SECONDARY_DISPLAY_ID);
}
@Test
@@ -101,6 +109,11 @@
}
@Test
+ public void testStartBgUser_onDefaultDisplay_visible() throws Exception {
+ visibleBgUserCannotBeStartedOnDefaultDisplayTest();
+ }
+
+ @Test
public void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
index c59834b..5176d68 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorTestCase.java
@@ -79,6 +79,11 @@
protected static final int OTHER_USER_ID = 666;
/**
+ * Id for yeat another simple user.
+ */
+ protected static final int YET_ANOTHER_USER_ID = 700;
+
+ /**
* Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
*
* <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
@@ -110,11 +115,14 @@
protected AsyncUserVisibilityListener.Factory mListenerFactory;
private final boolean mBackgroundUsersOnDisplaysEnabled;
+ private final boolean mBackgroundUserOnDefaultDisplayAllowed;
protected UserVisibilityMediator mMediator;
- protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled) {
+ protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled,
+ boolean backgroundUserOnDefaultDisplayAllowed) {
mBackgroundUsersOnDisplaysEnabled = backgroundUsersOnDisplaysEnabled;
+ mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed;
}
@Before
@@ -123,7 +131,8 @@
Thread thread = mHandler.getLooper().getThread();
Log.i(TAG, "setFixtures(): using thread " + thread + " (from handler " + mHandler + ")");
mListenerFactory = new AsyncUserVisibilityListener.Factory(mExpect, thread);
- mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled, mHandler);
+ mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled,
+ mBackgroundUserOnDefaultDisplayAllowed, mHandler);
mDumpableDumperRule.addDumpable(mMediator);
}
@@ -170,14 +179,8 @@
listener.verify();
}
- @Test
- public final void testStartVisibleBgUser_onDefaultDisplay() throws Exception {
- visibleBgUserCannotBeStartedOnDefaultDisplayTest();
-
- assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
- }
-
- protected final void visibleBgUserCannotBeStartedOnDefaultDisplayTest() throws Exception {
+ protected final @UserIdInt int visibleBgUserCannotBeStartedOnDefaultDisplayTest()
+ throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
@@ -188,6 +191,8 @@
expectNoDisplayAssignedToUser(USER_ID);
listener.verify();
+
+ return USER_ID;
}
@Test
@@ -504,7 +509,14 @@
}
protected void assertStartUserResult(int actualResult, int expectedResult) {
- assertWithMessage("startUser() result (where %s=%s and %s=%s)",
+ assertStartUserResult(actualResult, expectedResult, "");
+ }
+
+ @SuppressWarnings("AnnotateFormatMethod")
+ protected void assertStartUserResult(int actualResult, int expectedResult,
+ String extraMessageFormat, Object... extraMessageArguments) {
+ String extraMessage = String.format(extraMessageFormat, extraMessageArguments);
+ assertWithMessage("startUser() result %s(where %s=%s and %s=%s)", extraMessage,
expectedResult, userAssignmentResultToString(expectedResult),
actualResult, userAssignmentResultToString(actualResult))
.that(actualResult).isEqualTo(expectedResult);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
index 627553b..49c6a88 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserVisibilityMediatorVisibleBackgroundUserTestCase.java
@@ -38,9 +38,9 @@
abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
extends UserVisibilityMediatorTestCase {
- UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled)
- throws Exception {
- super(backgroundUsersOnDisplaysEnabled);
+ UserVisibilityMediatorVisibleBackgroundUserTestCase(boolean backgroundUsersOnDisplaysEnabled,
+ boolean backgroundUserOnDefaultDisplayAllowed) throws Exception {
+ super(backgroundUsersOnDisplaysEnabled, backgroundUserOnDefaultDisplayAllowed);
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
index a924207..19b5ad6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -29,6 +29,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER;
+import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER_CROP;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;
@@ -59,6 +60,7 @@
import android.content.pm.ServiceInfo;
import android.graphics.Color;
import android.hardware.display.DisplayManager;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -100,6 +102,8 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -158,6 +162,9 @@
sContext.getTestablePermissions().setPermission(
android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT,
PackageManager.PERMISSION_GRANTED);
+ sContext.getTestablePermissions().setPermission(
+ android.Manifest.permission.READ_WALLPAPER_INTERNAL,
+ PackageManager.PERMISSION_GRANTED);
doNothing().when(sContext).sendBroadcastAsUser(any(), any());
//Wallpaper components
@@ -494,6 +501,50 @@
colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME);
}
+ @Test
+ public void getWallpaperWithFeature_getCropped_returnsCropFile() throws Exception {
+ File cropSystemWallpaperFile =
+ new File(WallpaperUtils.getWallpaperDir(USER_SYSTEM), WALLPAPER_CROP);
+ cropSystemWallpaperFile.createNewFile();
+ try (FileOutputStream outputStream = new FileOutputStream(cropSystemWallpaperFile)) {
+ outputStream.write("Crop system wallpaper".getBytes());
+ }
+
+ ParcelFileDescriptor pfd =
+ mService.getWallpaperWithFeature(
+ sContext.getPackageName(),
+ sContext.getAttributionTag(),
+ /* cb= */ null,
+ FLAG_SYSTEM,
+ /* outParams= */ null,
+ USER_SYSTEM,
+ /* getCropped= */ true);
+
+ assertPfdAndFileContentsEqual(pfd, cropSystemWallpaperFile);
+ }
+
+ @Test
+ public void getWallpaperWithFeature_notGetCropped_returnsOriginalFile() throws Exception {
+ File originalSystemWallpaperFile =
+ new File(WallpaperUtils.getWallpaperDir(USER_SYSTEM), WALLPAPER);
+ originalSystemWallpaperFile.createNewFile();
+ try (FileOutputStream outputStream = new FileOutputStream(originalSystemWallpaperFile)) {
+ outputStream.write("Original system wallpaper".getBytes());
+ }
+
+ ParcelFileDescriptor pfd =
+ mService.getWallpaperWithFeature(
+ sContext.getPackageName(),
+ sContext.getAttributionTag(),
+ /* cb= */ null,
+ FLAG_SYSTEM,
+ /* outParams= */ null,
+ USER_SYSTEM,
+ /* getCropped= */ false);
+
+ assertPfdAndFileContentsEqual(pfd, originalSystemWallpaperFile);
+ }
+
// Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
// non-current user must not bind to wallpaper service.
private void verifyNoConnectionBeforeLastUser(int lastUserId) {
@@ -529,4 +580,22 @@
data.mHeight >= DISPLAY_SIZE_DIMENSION);
});
}
+
+ /**
+ * Asserts that the contents of the given {@link ParcelFileDescriptor} and {@link File} contain
+ * exactly the same bytes.
+ *
+ * Both the PFD and File contents will be loaded to memory. The PFD will be closed at the end.
+ */
+ private static void assertPfdAndFileContentsEqual(ParcelFileDescriptor pfd, File file)
+ throws IOException {
+ try (ParcelFileDescriptor.AutoCloseInputStream pfdInputStream =
+ new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ FileInputStream fileInputStream = new FileInputStream(file)
+ ) {
+ String pfdContents = new String(pfdInputStream.readAllBytes());
+ String fileContents = new String(fileInputStream.readAllBytes());
+ assertEquals(pfdContents, fileContents);
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
index 13d93cb..d9461aa 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
@@ -17,7 +17,6 @@
package com.android.server.accessibility;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS;
-import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
@@ -305,9 +304,7 @@
mSystemActionPerformer.performSystemAction(
AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
verify(mMockScreenshotHelper).takeScreenshot(
- eq(TAKE_SCREENSHOT_FULLSCREEN),
- eq(SCREENSHOT_ACCESSIBILITY_ACTIONS),
- any(Handler.class), any());
+ eq(SCREENSHOT_ACCESSIBILITY_ACTIONS), any(Handler.class), any());
}
// PendingIntent is a final class and cannot be mocked. So we are using this
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
index e6ab73a..162855a 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
@@ -119,12 +119,13 @@
final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive(
annotation);
mAnrHelper.appNotResponding(mAnrApp, activityShortComponentName, appInfo,
- parentShortComponentName, parentProcess, aboveSystem, timeoutRecord);
+ parentShortComponentName, parentProcess, aboveSystem, timeoutRecord,
+ /*isContinuousAnr*/ false);
verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS)).appNotResponding(
eq(activityShortComponentName), eq(appInfo), eq(parentShortComponentName),
eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mExecutorService),
- eq(false) /* onlyDumpSelf */);
+ eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/);
}
@Test
@@ -137,13 +138,14 @@
processingLatch.await();
return null;
}).when(mAnrApp.mErrorState).appNotResponding(anyString(), any(), any(), any(),
- anyBoolean(), any(), any(), anyBoolean());
+ anyBoolean(), any(), any(), anyBoolean(), anyBoolean());
final ApplicationInfo appInfo = new ApplicationInfo();
final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive(
"annotation");
final Runnable reportAnr = () -> mAnrHelper.appNotResponding(mAnrApp,
"activityShortComponentName", appInfo, "parentShortComponentName",
- null /* parentProcess */, false /* aboveSystem */, timeoutRecord);
+ null /* parentProcess */, false /* aboveSystem */, timeoutRecord,
+ false /*isContinuousAnr*/);
reportAnr.run();
// This should be skipped because the pid is pending in queue.
reportAnr.run();
@@ -160,6 +162,6 @@
// There is only one ANR reported.
verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS).only()).appNotResponding(
anyString(), any(), any(), any(), anyBoolean(), any(), eq(mExecutorService),
- anyBoolean());
+ anyBoolean(), anyBoolean());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
index 9cada91..6350e22 100644
--- a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
@@ -202,6 +202,7 @@
TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchNoFocusedWindow(annotation);
processErrorState.appNotResponding(null /* activityShortComponentName */, null /* aInfo */,
null /* parentShortComponentName */, null /* parentProcess */,
- false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */);
+ false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */,
+ false /*isContinuousAnr*/);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index eb99e30..6a4435f 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -51,6 +51,7 @@
import android.companion.AssociationInfo;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.IVirtualDeviceIntentInterceptor;
+import android.companion.virtual.IVirtualDeviceSoundEffectListener;
import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioConfigChangedCallback;
import android.companion.virtual.audio.IAudioRoutingCallback;
@@ -75,6 +76,7 @@
import android.hardware.input.VirtualNavigationTouchpadConfig;
import android.hardware.input.VirtualTouchEvent;
import android.hardware.input.VirtualTouchscreenConfig;
+import android.media.AudioManager;
import android.net.MacAddress;
import android.net.Uri;
import android.os.Binder;
@@ -223,6 +225,8 @@
@Mock
private IVirtualDeviceActivityListener mActivityListener;
@Mock
+ private IVirtualDeviceSoundEffectListener mSoundEffectListener;
+ @Mock
private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
@Mock
private VirtualDeviceManagerInternal.VirtualDisplayListener mDisplayListener;
@@ -332,7 +336,7 @@
new CameraAccessController(mContext, mLocalService, mCameraAccessBlockedCallback);
mAssociationInfo = new AssociationInfo(/* associationId= */ 1, 0, null,
- MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0);
+ MacAddress.BROADCAST_ADDRESS, "", null, null, true, false, false, 0, 0, -1);
mVdms = new VirtualDeviceManagerService(mContext);
mLocalService = mVdms.getLocalServiceInstance();
@@ -1572,6 +1576,13 @@
intent.filterEquals(blockedAppIntent)), any(), any());
}
+ @Test
+ public void playSoundEffect_callsSoundEffectListener() throws Exception {
+ mVdm.playSoundEffect(mDeviceImpl.getDeviceId(), AudioManager.FX_KEY_CLICK);
+
+ verify(mSoundEffectListener).onPlaySoundEffect(AudioManager.FX_KEY_CLICK);
+ }
+
private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid) {
VirtualDeviceParams params = new VirtualDeviceParams.Builder()
.setBlockedActivities(getBlockedActivities())
@@ -1585,7 +1596,8 @@
mAssociationInfo, new Binder(), ownerUid, virtualDeviceId,
mInputController, mSensorController, mCameraAccessController,
/* onDeviceCloseListener= */ deviceId -> mVdms.removeVirtualDevice(deviceId),
- mPendingTrampolineCallback, mActivityListener, mRunningAppsChangedCallback, params);
+ mPendingTrampolineCallback, mActivityListener, mSoundEffectListener,
+ mRunningAppsChangedCallback, params);
mVdms.addVirtualDevice(virtualDeviceImpl);
return virtualDeviceImpl;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 210aeef..4998a6c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1085,27 +1085,6 @@
// DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
}
- /**
- * TODO(b/174859111): move to automotive-only section
- * Test for {@link DevicePolicyManager#setDeviceOwner} in headless system user mode.
- */
- @Test
- public void testSetDeviceOwner_headlessSystemUserMode() throws Exception {
- when(getServices().userManagerForMock.isHeadlessSystemUserMode()).thenReturn(true);
- setDeviceOwner_headlessSystemUser();
-
- // Try to set a profile owner on the same user, which should fail.
- setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
- dpm.setActiveAdmin(admin2, /* refreshing= */ true, CALLER_USER_HANDLE);
- assertExpectException(IllegalStateException.class,
- /* messageRegex= */ "profile owner is already set",
- () -> dpm.setProfileOwner(admin2, CALLER_USER_HANDLE));
-
- // DO admin can't be deactivated.
- dpm.removeActiveAdmin(admin1);
- assertThat(dpm.isAdminActive(admin1)).isTrue();
- }
-
private void setDeviceOwner() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index a45144e..82f6493 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -67,6 +67,9 @@
new DeviceState(0, "DEFAULT", 0 /* flags */);
private static final DeviceState OTHER_DEVICE_STATE =
new DeviceState(1, "OTHER", 0 /* flags */);
+ private static final DeviceState DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP =
+ new DeviceState(2, "DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP",
+ DeviceState.FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP /* flags */);
// A device state that is not reported as being supported for the default test provider.
private static final DeviceState UNSUPPORTED_DEVICE_STATE =
new DeviceState(255, "UNSUPPORTED", 0 /* flags */);
@@ -77,6 +80,7 @@
private TestDeviceStateProvider mProvider;
private DeviceStateManagerService mService;
private TestSystemPropertySetter mSysPropSetter;
+ private WindowProcessController mWindowProcessController;
@Before
public void setup() {
@@ -88,10 +92,10 @@
// Necessary to allow us to check for top app process id in tests
mService.mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
- WindowProcessController windowProcessController = mock(WindowProcessController.class);
+ mWindowProcessController = mock(WindowProcessController.class);
when(mService.mActivityTaskManagerInternal.getTopApp())
- .thenReturn(windowProcessController);
- when(windowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
+ .thenReturn(mWindowProcessController);
+ when(mWindowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
flushHandler(); // Flush the handler to ensure the initial values are committed.
}
@@ -201,7 +205,7 @@
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE);
+ OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE});
flushHandler();
@@ -234,10 +238,10 @@
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE);
+ OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE});
+ OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP});
flushHandler();
// The current committed and requests states do not change because the current state remains
@@ -248,7 +252,7 @@
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE);
+ OTHER_DEVICE_STATE, DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP);
// The callback wasn't notified about a change in supported states as the states have not
// changed.
@@ -261,7 +265,8 @@
assertNotNull(info);
assertArrayEquals(info.supportedStates,
new int[] { DEFAULT_DEVICE_STATE.getIdentifier(),
- OTHER_DEVICE_STATE.getIdentifier() });
+ OTHER_DEVICE_STATE.getIdentifier(),
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP.getIdentifier()});
assertEquals(info.baseState, DEFAULT_DEVICE_STATE.getIdentifier());
assertEquals(info.currentState, DEFAULT_DEVICE_STATE.getIdentifier());
}
@@ -513,6 +518,54 @@
OTHER_DEVICE_STATE.getIdentifier());
}
+ @Test
+ public void requestState_flagCancelWhenRequesterNotOnTop_onDeviceSleep()
+ throws RemoteException {
+ requestState_flagCancelWhenRequesterNotOnTop_common(
+ // When the device is awake, the state should not change
+ () -> mService.mOverrideRequestScreenObserver.onAwakeStateChanged(true),
+ // When the device is in sleep mode, the state should be canceled
+ () -> mService.mOverrideRequestScreenObserver.onAwakeStateChanged(false)
+ );
+ }
+
+ @Test
+ public void requestState_flagCancelWhenRequesterNotOnTop_onKeyguardShow()
+ throws RemoteException {
+ requestState_flagCancelWhenRequesterNotOnTop_common(
+ // When the keyguard is not showing, the state should not change
+ () -> mService.mOverrideRequestScreenObserver.onKeyguardStateChanged(false),
+ // When the keyguard is showing, the state should be canceled
+ () -> mService.mOverrideRequestScreenObserver.onKeyguardStateChanged(true)
+ );
+ }
+
+ @Test
+ public void requestState_flagCancelWhenRequesterNotOnTop_onTaskStackChanged()
+ throws RemoteException {
+ requestState_flagCancelWhenRequesterNotOnTop_common(
+ // When the app is foreground, the state should not change
+ () -> {
+ int pid = Binder.getCallingPid();
+ when(mWindowProcessController.getPid()).thenReturn(pid);
+ try {
+ mService.mOverrideRequestTaskStackListener.onTaskStackChanged();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ },
+ // When the app is not foreground, the state should change
+ () -> {
+ when(mWindowProcessController.getPid()).thenReturn(FAKE_PROCESS_ID);
+ try {
+ mService.mOverrideRequestTaskStackListener.onTaskStackChanged();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ );
+ }
+
@FlakyTest(bugId = 200332057)
@Test
public void requestState_becomesUnsupported() throws RemoteException {
@@ -743,6 +796,84 @@
Assert.assertTrue(Arrays.equals(expected, actual));
}
+ /**
+ * Common code to verify the handling of FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP flag.
+ *
+ * The device state with FLAG_CANCEL_WHEN_REQUESTER_NOT_ON_TOP should be automatically canceled
+ * when certain events happen, e.g. when the top activity belongs to another app or when the
+ * device goes into the sleep mode.
+ *
+ * @param noChangeEvent an event that should not trigger auto cancellation of the state.
+ * @param autoCancelEvent an event that should trigger auto cancellation of the state.
+ * @throws RemoteException when the service throws exceptions.
+ */
+ private void requestState_flagCancelWhenRequesterNotOnTop_common(
+ Runnable noChangeEvent,
+ Runnable autoCancelEvent
+ ) throws RemoteException {
+ TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
+ mService.getBinderService().registerCallback(callback);
+ flushHandler();
+
+ final IBinder token = new Binder();
+ assertEquals(callback.getLastNotifiedStatus(token),
+ TestDeviceStateManagerCallback.STATUS_UNKNOWN);
+
+ mService.getBinderService().requestState(token,
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP.getIdentifier(),
+ 0 /* flags */);
+ flushHandler(2 /* count */);
+
+ assertEquals(callback.getLastNotifiedStatus(token),
+ TestDeviceStateManagerCallback.STATUS_ACTIVE);
+
+ // Committed state changes as there is a requested override.
+ assertDeviceStateConditions(
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ DEFAULT_DEVICE_STATE, /* base state */
+ true /* isOverrideState */);
+
+ noChangeEvent.run();
+ flushHandler();
+ assertEquals(callback.getLastNotifiedStatus(token),
+ TestDeviceStateManagerCallback.STATUS_ACTIVE);
+ assertDeviceStateConditions(
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP,
+ DEFAULT_DEVICE_STATE, /* base state */
+ true /* isOverrideState */);
+
+ autoCancelEvent.run();
+ flushHandler();
+ assertEquals(callback.getLastNotifiedStatus(token),
+ TestDeviceStateManagerCallback.STATUS_CANCELED);
+ assertDeviceStateConditions(DEFAULT_DEVICE_STATE, DEFAULT_DEVICE_STATE,
+ false /* isOverrideState */);
+ }
+
+ /**
+ * Verify that the current device state and base state match the expected values.
+ *
+ * @param state the expected committed state.
+ * @param baseState the expected base state.
+ * @param isOverrideState whether a state override is active.
+ */
+ private void assertDeviceStateConditions(
+ DeviceState state, DeviceState baseState, boolean isOverrideState) {
+ assertEquals(mService.getCommittedState(), Optional.of(state));
+ assertEquals(mService.getBaseState(), Optional.of(baseState));
+ assertEquals(mSysPropSetter.getValue(),
+ state.getIdentifier() + ":" + state.getName());
+ assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
+ state.getIdentifier());
+ if (isOverrideState) {
+ // When a state override is active, the committed state should batch the override state.
+ assertEquals(mService.getOverrideState().get(), state);
+ } else {
+ // When there is no state override, the override state should be empty.
+ assertFalse(mService.getOverrideState().isPresent());
+ }
+ }
+
private static final class TestDeviceStatePolicy extends DeviceStatePolicy {
private final DeviceStateProvider mProvider;
private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE;
@@ -801,8 +932,10 @@
}
private static final class TestDeviceStateProvider implements DeviceStateProvider {
- private DeviceState[] mSupportedDeviceStates = new DeviceState[]{ DEFAULT_DEVICE_STATE,
- OTHER_DEVICE_STATE };
+ private DeviceState[] mSupportedDeviceStates = new DeviceState[]{
+ DEFAULT_DEVICE_STATE,
+ OTHER_DEVICE_STATE,
+ DEVICE_STATE_CANCEL_WHEN_REQUESTER_NOT_ON_TOP};
private Listener mListener;
@Override
diff --git a/services/tests/servicestests/src/com/android/server/display/HbmEventTest.java b/services/tests/servicestests/src/com/android/server/display/HbmEventTest.java
deleted file mode 100644
index 24fc348..0000000
--- a/services/tests/servicestests/src/com/android/server/display/HbmEventTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.display;
-
-import static org.junit.Assert.assertEquals;
-
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class HbmEventTest {
- private long mStartTimeMillis;
- private long mEndTimeMillis;
- private HbmEvent mHbmEvent;
-
- @Before
- public void setUp() {
- mStartTimeMillis = 10;
- mEndTimeMillis = 20;
- mHbmEvent = new HbmEvent(mStartTimeMillis, mEndTimeMillis);
- }
-
- @Test
- public void getCorrectValues() {
- assertEquals(mHbmEvent.getStartTimeMillis(), mStartTimeMillis);
- assertEquals(mHbmEvent.getEndTimeMillis(), mEndTimeMillis);
- }
-
- @Test
- public void toStringGeneratesExpectedString() {
- String actualString = mHbmEvent.toString();
- String expectedString = "HbmEvent: {startTimeMillis:" + mStartTimeMillis
- + ", endTimeMillis: " + mEndTimeMillis + "}, total: "
- + ((mEndTimeMillis - mStartTimeMillis) / 1000) + "]";
- assertEquals(actualString, expectedString);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index 2655c3f..a1e5ce7 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -96,7 +96,6 @@
private Binder mDisplayToken;
private String mDisplayUniqueId;
private Context mContextSpy;
- private HighBrightnessModeMetadata mHighBrightnessModeMetadata;
@Rule
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
@@ -119,7 +118,6 @@
mTestLooper = new TestLooper(mClock::now);
mDisplayToken = null;
mDisplayUniqueId = "unique_id";
-
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
when(mContextSpy.getContentResolver()).thenReturn(resolver);
@@ -136,8 +134,7 @@
initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken,
- mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {},
- null, mContextSpy);
+ mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {}, mContextSpy);
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
}
@@ -147,8 +144,7 @@
initHandler(null);
final HighBrightnessModeController hbmc = new HighBrightnessModeController(
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken,
- mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {},
- null, mContextSpy);
+ mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX, null, null, () -> {}, mContextSpy);
hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
@@ -703,12 +699,9 @@
// Creates instance with standard initialization values.
private HighBrightnessModeController createDefaultHbm(OffsettableClock clock) {
initHandler(clock);
- if (mHighBrightnessModeMetadata == null) {
- mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
- }
return new HighBrightnessModeController(mInjectorMock, mHandler, DISPLAY_WIDTH,
DISPLAY_HEIGHT, mDisplayToken, mDisplayUniqueId, DEFAULT_MIN, DEFAULT_MAX,
- DEFAULT_HBM_DATA, null, () -> {}, mHighBrightnessModeMetadata, mContextSpy);
+ DEFAULT_HBM_DATA, null, () -> {}, mContextSpy);
}
private void initHandler(OffsettableClock clock) {
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeMetadataTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeMetadataTest.java
deleted file mode 100644
index ede54e0..0000000
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeMetadataTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.display;
-
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public final class HighBrightnessModeMetadataTest {
- private HighBrightnessModeMetadata mHighBrightnessModeMetadata;
-
- private long mRunningStartTimeMillis = -1;
-
- @Before
- public void setUp() {
- mHighBrightnessModeMetadata = new HighBrightnessModeMetadata();
- }
-
- @Test
- public void checkDefaultValues() {
- assertEquals(mHighBrightnessModeMetadata.getRunningStartTimeMillis(),
- mRunningStartTimeMillis);
- assertEquals(mHighBrightnessModeMetadata.getHbmEventQueue().size(), 0);
- }
-
- @Test
- public void checkSetValues() {
- mRunningStartTimeMillis = 10;
- mHighBrightnessModeMetadata.setRunningStartTimeMillis(mRunningStartTimeMillis);
- assertEquals(mHighBrightnessModeMetadata.getRunningStartTimeMillis(),
- mRunningStartTimeMillis);
- HbmEvent expectedHbmEvent = new HbmEvent(10, 20);
- mHighBrightnessModeMetadata.addHbmEvent(expectedHbmEvent);
- HbmEvent actualHbmEvent = mHighBrightnessModeMetadata.getHbmEventQueue().peekFirst();
- assertEquals(expectedHbmEvent.toString(), actualHbmEvent.toString());
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index a9b7143..5ef762b 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -691,6 +691,7 @@
// 2) Mark the displays as STATE_OFF so that it can continue with transition
// 3) Send DISPLAY_DEVICE_EVENT_CHANGE to inform the mapper of the new display state
// 4) Dispatch handler events.
+ mLogicalDisplayMapper.onBootCompleted();
mLogicalDisplayMapper.setDeviceStateLocked(0, false);
mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
advanceTime(1000);
diff --git a/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
new file mode 100644
index 0000000..6c5a569
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/grammaticalinflection/GrammaticalInflectionBackupTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.grammaticalinflection;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.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.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.collect.Maps;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class GrammaticalInflectionBackupTest {
+ private static final int DEFAULT_USER_ID = 0;
+ private static final String DEFAULT_PACKAGE_NAME = "com.test.package.name";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private PackageManager mMockPackageManager;
+ @Mock
+ private GrammaticalInflectionService mGrammaticalInflectionService;
+
+ private GrammaticalInflectionBackupHelper mBackupHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ mBackupHelper = new GrammaticalInflectionBackupHelper(
+ mGrammaticalInflectionService, mMockPackageManager);
+ }
+
+ @Test
+ public void testBackupPayload_noAppsInstalled_returnsNull() {
+ assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
+ }
+
+ @Test
+ public void testBackupPayload_AppsInstalled_returnsGender()
+ throws IOException, ClassNotFoundException {
+ mockAppInstalled();
+ mockGetApplicationGrammaticalGender(Configuration.GRAMMATICAL_GENDER_MASCULINE);
+
+ HashMap<String, Integer> payload =
+ readFromByteArray(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
+
+ // verify the payload
+ HashMap<String, Integer> expectationMap = new HashMap<>();
+ expectationMap.put(DEFAULT_PACKAGE_NAME, Configuration.GRAMMATICAL_GENDER_MASCULINE);
+ assertTrue(Maps.difference(payload, expectationMap).areEqual());
+ }
+
+ @Test
+ public void testApplyPayload_onPackageAdded_setApplicationGrammaticalGender()
+ throws IOException {
+ mockAppInstalled();
+
+ HashMap<String, Integer> testData = new HashMap<>();
+ testData.put(DEFAULT_PACKAGE_NAME, Configuration.GRAMMATICAL_GENDER_NEUTRAL);
+ mBackupHelper.stageAndApplyRestoredPayload(convertToByteArray(testData), DEFAULT_USER_ID);
+ mBackupHelper.onPackageAdded(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
+
+ verify(mGrammaticalInflectionService).setRequestedApplicationGrammaticalGender(
+ eq(DEFAULT_PACKAGE_NAME),
+ eq(DEFAULT_USER_ID),
+ eq(Configuration.GRAMMATICAL_GENDER_NEUTRAL));
+ }
+
+ private void mockAppInstalled() {
+ ApplicationInfo dummyApp = new ApplicationInfo();
+ dummyApp.packageName = DEFAULT_PACKAGE_NAME;
+ doReturn(List.of(dummyApp)).when(mMockPackageManager)
+ .getInstalledApplicationsAsUser(any(), anyInt());
+ }
+
+ private void mockGetApplicationGrammaticalGender(int grammaticalGender) {
+ doReturn(grammaticalGender).when(mGrammaticalInflectionService)
+ .getApplicationGrammaticalGender(
+ eq(DEFAULT_PACKAGE_NAME), eq(DEFAULT_USER_ID));
+ }
+
+ private byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) throws IOException{
+ try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final ObjectOutputStream objStream = new ObjectOutputStream(out)) {
+ objStream.writeObject(pkgGenderInfo);
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+
+ private HashMap<String, Integer> readFromByteArray(byte[] payload)
+ throws IOException, ClassNotFoundException {
+ HashMap<String, Integer> data;
+
+ try (ByteArrayInputStream byteIn = new ByteArrayInputStream(payload);
+ ObjectInputStream in = new ObjectInputStream(byteIn)) {
+ data = (HashMap<String, Integer>) in.readObject();
+ } catch (IOException | ClassNotFoundException e) {
+ throw e;
+ }
+ return data;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
index 3ce747f..e1a04ad5 100644
--- a/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/input/BatteryControllerTests.kt
@@ -25,6 +25,7 @@
import android.hardware.BatteryState.STATUS_DISCHARGING
import android.hardware.BatteryState.STATUS_FULL
import android.hardware.BatteryState.STATUS_UNKNOWN
+import android.hardware.input.HostUsiVersion
import android.hardware.input.IInputDeviceBatteryListener
import android.hardware.input.IInputDeviceBatteryState
import android.hardware.input.IInputDevicesChangedListener
@@ -86,7 +87,7 @@
.setDescriptor("descriptor $deviceId")
.setExternal(true)
.setHasBattery(hasBattery)
- .setSupportsUsi(supportsUsi)
+ .setUsiVersion(if (supportsUsi) HostUsiVersion(1, 0) else null)
.setGeneration(generation)
.build()
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
index 0fd6a9e..a0f03bb 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
@@ -22,7 +22,6 @@
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER_IMPORTANT;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_EJ;
-import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_FGS;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
import static com.android.server.job.JobConcurrencyManager.workTypeToString;
@@ -59,7 +58,8 @@
private static final double[] EQUAL_PROBABILITY_CDF =
buildWorkTypeCdf(1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES,
- 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES);
+ 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES,
+ 1.0 / NUM_WORK_TYPES);
private Random mRandom;
private WorkCountTracker mWorkCountTracker;
@@ -72,8 +72,9 @@
@NonNull
private static double[] buildWorkTypeCdf(
- double pTop, double pFgs, double pEj, double pBg, double pBgUserImp, double pBgUser) {
- return buildCdf(pTop, pFgs, pEj, pBg, pBgUserImp, pBgUser);
+ double pTop, double pFgs, double pUi, double pEj, double pBg,
+ double pBgUserImp, double pBgUser) {
+ return buildCdf(pTop, pFgs, pUi, pEj, pBg, pBgUserImp, pBgUser);
}
@NonNull
@@ -108,23 +109,9 @@
@JobConcurrencyManager.WorkType
static int getRandomWorkType(double[] cdf, double rand) {
+ assertThat(cdf.length).isEqualTo(NUM_WORK_TYPES);
final int index = getRandomIndex(cdf, rand);
- switch (index) {
- case 0:
- return WORK_TYPE_TOP;
- case 1:
- return WORK_TYPE_FGS;
- case 2:
- return WORK_TYPE_EJ;
- case 3:
- return WORK_TYPE_BG;
- case 4:
- return WORK_TYPE_BGUSER_IMPORTANT;
- case 5:
- return WORK_TYPE_BGUSER;
- default:
- throw new IllegalStateException("Unknown work type");
- }
+ return 1 << index;
}
/**
@@ -326,7 +313,7 @@
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0.5, 0, 0);
+ final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0, 0.5, 0, 0);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
@@ -344,7 +331,7 @@
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
+ final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.75, .2, .05);
final double probStart = 0.5;
@@ -362,7 +349,7 @@
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, .2f), Pair.create(WORK_TYPE_BGUSER, .1f));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
+ final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.05, .95);
final double probStart = 0.5;
@@ -382,7 +369,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 2.0f / 3));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.8, 0.02, .08);
+ final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0, 0.8, 0.02, .08);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
@@ -402,7 +389,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0.85, 0.05, 0, 0.1, 0, 0);
+ final double[] cdf = buildWorkTypeCdf(0.8, 0.05, 0.05, 0, 0.1, 0, 0);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
@@ -422,7 +409,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.1, 0.05, .75);
+ final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0, 0.1, 0.05, .75);
final double[] numTypesCdf = buildCdf(0.5, 0.5);
final double probStart = 0.5;
@@ -443,7 +430,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0.05, 0, 0.05);
+ final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0, 0.05, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
@@ -464,7 +451,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.5, 0, 0.5);
+ final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0, 0.5, 0, 0.5);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
@@ -485,7 +472,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.1, 0, 0.9);
+ final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0, 0.1, 0, 0.9);
final double[] numTypesCdf = buildCdf(0.9, 0.1);
final double probStart = 0.5;
@@ -506,7 +493,7 @@
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
- final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.9, 0, 0.1);
+ final double[] cdf = buildWorkTypeCdf(0, 0, .4, 0, 0.5, 0, 0.1);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
@@ -525,7 +512,7 @@
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0, 0, 0);
+ final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.25, 0.25, 0, 0, 0);
final double[] numTypesCdf = buildCdf(0.1, 0.7, 0.2);
final double probStart = 0.5;
@@ -566,7 +553,7 @@
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(.1, 0, 0.5, 0.35, 0, 0.05);
+ final double[] cdf = buildWorkTypeCdf(.1, 0, 0.05, 0.45, 0.35, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
@@ -586,7 +573,7 @@
List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.4, 0.1, 0, 0.4);
+ final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.2, 0.2, 0.1, 0, 0.4);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
@@ -607,7 +594,7 @@
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 7),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 7));
final double probStop = 0.4;
- final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.25, 0.05, 0.3, 0.3);
+ final double[] cdf = buildWorkTypeCdf(0.01, 0.02, 0.09, 0.25, 0.05, 0.3, 0.3);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
index bd5a063..94dfae3 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
@@ -21,6 +21,7 @@
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_EJ;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_FGS;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
+import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_UI;
import static com.android.server.job.JobConcurrencyManager.workTypeToString;
import static org.junit.Assert.assertEquals;
@@ -47,6 +48,7 @@
private static final String KEY_MAX_TOTAL = "concurrency_max_total_test";
private static final String KEY_MAX_RATIO_TOP = "concurrency_max_ratio_top_test";
private static final String KEY_MAX_RATIO_FGS = "concurrency_max_ratio_fgs_test";
+ private static final String KEY_MAX_RATIO_UI = "concurrency_max_ratio_ui_test";
private static final String KEY_MAX_RATIO_EJ = "concurrency_max_ratio_ej_test";
private static final String KEY_MAX_RATIO_BG = "concurrency_max_ratio_bg_test";
private static final String KEY_MAX_RATIO_BGUSER_IMPORTANT =
@@ -54,6 +56,7 @@
private static final String KEY_MAX_RATIO_BGUSER = "concurrency_max_ratio_bguser_test";
private static final String KEY_MIN_RATIO_TOP = "concurrency_min_ratio_top_test";
private static final String KEY_MIN_RATIO_FGS = "concurrency_min_ratio_fgs_test";
+ private static final String KEY_MIN_RATIO_UI = "concurrency_min_ratio_ui_test";
private static final String KEY_MIN_RATIO_EJ = "concurrency_min_ratio_ej_test";
private static final String KEY_MIN_RATIO_BG = "concurrency_min_ratio_bg_test";
private static final String KEY_MIN_RATIO_BGUSER_IMPORTANT =
@@ -326,31 +329,35 @@
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
- .setInt(KEY_MAX_TOTAL, 16)
+ .setInt(KEY_MAX_TOTAL, 32)
.setFloat(KEY_MAX_RATIO_TOP, 1f)
- .setFloat(KEY_MIN_RATIO_TOP, 1.0f / 16)
- .setFloat(KEY_MAX_RATIO_FGS, 15.0f / 16)
- .setFloat(KEY_MIN_RATIO_FGS, 2.0f / 16)
- .setFloat(KEY_MAX_RATIO_EJ, 14.0f / 16)
- .setFloat(KEY_MIN_RATIO_EJ, 3.0f / 16)
- .setFloat(KEY_MAX_RATIO_BG, 13.0f / 16)
- .setFloat(KEY_MIN_RATIO_BG, 3.0f / 16)
- .setFloat(KEY_MAX_RATIO_BGUSER_IMPORTANT, 12.0f / 16)
- .setFloat(KEY_MIN_RATIO_BGUSER_IMPORTANT, 2.0f / 16)
- .setFloat(KEY_MAX_RATIO_BGUSER, 11.0f / 16)
- .setFloat(KEY_MIN_RATIO_BGUSER, 2.0f / 16)
+ .setFloat(KEY_MIN_RATIO_TOP, 1.0f / 32)
+ .setFloat(KEY_MAX_RATIO_FGS, 15.0f / 32)
+ .setFloat(KEY_MIN_RATIO_FGS, 2.0f / 32)
+ .setFloat(KEY_MAX_RATIO_UI, 10.0f / 32)
+ .setFloat(KEY_MIN_RATIO_UI, 4.0f / 32)
+ .setFloat(KEY_MAX_RATIO_EJ, 14.0f / 32)
+ .setFloat(KEY_MIN_RATIO_EJ, 3.0f / 32)
+ .setFloat(KEY_MAX_RATIO_BG, 13.0f / 32)
+ .setFloat(KEY_MIN_RATIO_BG, 3.0f / 32)
+ .setFloat(KEY_MAX_RATIO_BGUSER_IMPORTANT, 12.0f / 32)
+ .setFloat(KEY_MIN_RATIO_BGUSER_IMPORTANT, 2.0f / 32)
+ .setFloat(KEY_MAX_RATIO_BGUSER, 11.0f / 32)
+ .setFloat(KEY_MIN_RATIO_BGUSER, 2.0f / 32)
.build(),
- /* limit */ 16,
+ /* limit */ 32,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
- /*expected*/ true, 16,
+ /*expected*/ true, 32,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_FGS, 2),
+ Pair.create(WORK_TYPE_UI, 4),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 3),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
Pair.create(WORK_TYPE_BGUSER, 2)),
/* max */
- List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15),
+ List.of(Pair.create(WORK_TYPE_TOP, 32), Pair.create(WORK_TYPE_FGS, 15),
+ Pair.create(WORK_TYPE_UI, 10),
Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 12),
Pair.create(WORK_TYPE_BGUSER, 11)));
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index fa8d866..93f6db7 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -500,6 +500,7 @@
// The cached conversations are above the limit because every conversation has active
// notifications. To uncache one of them, the notifications for that conversation need to
// be dismissed.
+ String notificationKey = "";
for (int i = 0; i < DataManager.MAX_CACHED_RECENT_SHORTCUTS + 1; i++) {
String shortcutId = TEST_SHORTCUT_ID + i;
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
@@ -507,11 +508,13 @@
shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
mDataManager.addOrUpdateConversationInfo(shortcut);
when(mNotification.getShortcutId()).thenReturn(shortcutId);
- sendGenericNotification();
+ notificationKey = String.format("notification-key-%d", i);
+ sendGenericNotificationWithKey(notificationKey);
}
// Post another notification for the last conversation.
- sendGenericNotification();
+ String otherNotificationKey = "other-notification-key";
+ sendGenericNotificationWithKey(otherNotificationKey);
// Removing one of the two notifications does not un-cache the shortcut.
listenerService.onNotificationRemoved(mGenericSbn, null,
@@ -520,6 +523,7 @@
anyInt(), any(), anyString(), any(), anyInt(), anyInt());
// Removing the second notification un-caches the shortcut.
+ when(mGenericSbn.getKey()).thenReturn(notificationKey);
listenerService.onNotificationRemoved(mGenericSbn, null,
NotificationListenerService.REASON_CANCEL_ALL);
verify(mShortcutServiceInternal).uncacheShortcuts(
@@ -687,6 +691,35 @@
}
@Test
+ public void testGetConversation_trackActiveConversations() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+ assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID)).isNull();
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ shortcut.setCached(ShortcutInfo.FLAG_PINNED);
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+ assertThat(mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID)).isNotNull();
+
+ sendGenericNotification();
+ sendGenericNotification();
+ ConversationChannel result = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID);
+ assertTrue(result.hasActiveNotifications());
+
+ // Both generic notifications have the same notification key, so a single dismiss will
+ // remove both of them.
+ NotificationListenerService listenerService =
+ mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+ listenerService.onNotificationRemoved(mGenericSbn, null,
+ NotificationListenerService.REASON_CANCEL);
+ ConversationChannel resultTwo = mDataManager.getConversation(TEST_PKG_NAME, USER_ID_PRIMARY,
+ TEST_SHORTCUT_ID);
+ assertFalse(resultTwo.hasActiveNotifications());
+ }
+
+ @Test
public void testGetConversation_unsyncedShortcut() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
@@ -1322,7 +1355,7 @@
sendGenericNotification();
- mDataManager.getRecentConversations(USER_ID_PRIMARY);
+ mDataManager.getRecentConversations(USER_ID_PRIMARY);
verify(mShortcutServiceInternal).getShortcuts(
anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
@@ -1693,6 +1726,12 @@
// "Sends" a notification to a non-customized notification channel - the notification channel
// is something generic like "messages" and the notification has a shortcut id
private void sendGenericNotification() {
+ sendGenericNotificationWithKey(GENERIC_KEY);
+ }
+
+ // "Sends" a notification to a non-customized notification channel with the specified key.
+ private void sendGenericNotificationWithKey(String key) {
+ when(mGenericSbn.getKey()).thenReturn(key);
when(mNotification.getChannelId()).thenReturn(PARENT_NOTIFICATION_CHANNEL_ID);
doAnswer(invocationOnMock -> {
NotificationListenerService.Ranking ranking = (NotificationListenerService.Ranking)
@@ -1708,7 +1747,7 @@
mParentNotificationChannel, null, null, true, 0, false, -1, false, null, null,
false, false, false, null, 0, false, 0);
return true;
- }).when(mRankingMap).getRanking(eq(GENERIC_KEY),
+ }).when(mRankingMap).getRanking(eq(key),
any(NotificationListenerService.Ranking.class));
NotificationListenerService listenerService =
mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
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 76a13f1..1305e07 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -26,10 +26,8 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
@@ -41,6 +39,7 @@
import android.provider.Settings;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
+import android.util.ArraySet;
import android.util.Slog;
import androidx.annotation.Nullable;
@@ -48,6 +47,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Range;
@@ -56,16 +57,14 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
import java.util.stream.Collectors;
-import javax.annotation.concurrent.GuardedBy;
-
/** Test {@link UserManager} functionality. */
@Postsubmit
@RunWith(AndroidJUnit4.class)
@@ -73,8 +72,6 @@
// Taken from UserManagerService
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // 30 years
- private static final int REMOVE_CHECK_INTERVAL_MILLIS = 500; // 0.5 seconds
- private static final int REMOVE_TIMEOUT_MILLIS = 60 * 1000; // 60 seconds
private static final int SWITCH_USER_TIMEOUT_SECONDS = 40; // 40 seconds
// Packages which are used during tests.
@@ -86,12 +83,10 @@
private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
- private final Object mUserRemoveLock = new Object();
-
private UserManager mUserManager = null;
private ActivityManager mActivityManager;
private PackageManager mPackageManager;
- private List<Integer> usersToRemove;
+ private ArraySet<Integer> mUsersToRemove;
private UserSwitchWaiter mUserSwitchWaiter;
@Before
@@ -101,30 +96,16 @@
mPackageManager = mContext.getPackageManager();
mUserSwitchWaiter = new UserSwitchWaiter(TAG, SWITCH_USER_TIMEOUT_SECONDS);
- IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case Intent.ACTION_USER_REMOVED:
- synchronized (mUserRemoveLock) {
- mUserRemoveLock.notifyAll();
- }
- break;
- }
- }
- }, filter);
-
+ mUsersToRemove = new ArraySet<>();
removeExistingUsers();
- usersToRemove = new ArrayList<>();
}
@After
public void tearDown() throws Exception {
mUserSwitchWaiter.close();
- for (Integer userId : usersToRemove) {
- removeUser(userId);
- }
+
+ // Making a copy of mUsersToRemove to avoid ConcurrentModificationException
+ mUsersToRemove.stream().toList().forEach(this::removeUser);
}
private void removeExistingUsers() {
@@ -406,13 +387,11 @@
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ true,
asHandle(currentUser));
try {
- synchronized (mUserRemoveLock) {
+ runThenWaitForUserRemoval(() -> {
assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(),
/* overrideDevicePolicy= */ true))
- .isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
- waitForUserRemovalLocked(user1.id);
- }
-
+ .isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
+ }, user1.id); // wait for user removal
} finally {
mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false,
asHandle(currentUser));
@@ -477,13 +456,12 @@
assertThat(hasUser(user1.id)).isTrue();
assertThat(getUser(user1.id).isEphemeral()).isTrue();
- // Switch back to the starting user.
- switchUser(startUser);
+ runThenWaitForUserRemoval(() -> {
+ // Switch back to the starting user.
+ switchUser(startUser);
+ // User will be removed once switch is complete
+ }, user1.id); // wait for user removal
- // User is removed once switch is complete
- synchronized (mUserRemoveLock) {
- waitForUserRemovalLocked(user1.id);
- }
assertThat(hasUser(user1.id)).isFalse();
}
@@ -495,19 +473,19 @@
// Switch to the user just created.
switchUser(testUser.id);
- switchUserThenRun(startUser, () -> {
- // While the user switch is happening, call removeUserWhenPossible for the current user.
- assertThat(mUserManager.removeUserWhenPossible(testUser.getUserHandle(), false))
- .isEqualTo(UserManager.REMOVE_RESULT_DEFERRED);
+ runThenWaitForUserRemoval(() -> {
+ switchUserThenRun(startUser, () -> {
+ // While the switch is happening, call removeUserWhenPossible for the current user.
+ assertThat(mUserManager.removeUserWhenPossible(testUser.getUserHandle(),
+ /* overrideDevicePolicy= */ false))
+ .isEqualTo(UserManager.REMOVE_RESULT_DEFERRED);
- assertThat(hasUser(testUser.id)).isTrue();
- assertThat(getUser(testUser.id).isEphemeral()).isTrue();
- });
+ assertThat(hasUser(testUser.id)).isTrue();
+ assertThat(getUser(testUser.id).isEphemeral()).isTrue();
+ }); // wait for user switch - startUser
+ // User will be removed once switch is complete
+ }, testUser.id); // wait for user removal
- // User is removed once switch is complete
- synchronized (mUserRemoveLock) {
- waitForUserRemovalLocked(testUser.id);
- }
assertThat(hasUser(testUser.id)).isFalse();
}
@@ -519,20 +497,20 @@
switchUserThenRun(testUser.id, () -> {
// While the user switch is happening, call removeUserWhenPossible for the target user.
- assertThat(mUserManager.removeUserWhenPossible(testUser.getUserHandle(), false))
+ assertThat(mUserManager.removeUserWhenPossible(testUser.getUserHandle(),
+ /* overrideDevicePolicy= */ false))
.isEqualTo(UserManager.REMOVE_RESULT_DEFERRED);
assertThat(hasUser(testUser.id)).isTrue();
assertThat(getUser(testUser.id).isEphemeral()).isTrue();
- });
+ }); // wait for user switch - testUser
- // Switch back to the starting user.
- switchUser(startUser);
+ runThenWaitForUserRemoval(() -> {
+ // Switch back to the starting user.
+ switchUser(startUser);
+ // User will be removed once switch is complete
+ }, testUser.id); // wait for user removal
- // User is removed once switch is complete
- synchronized (mUserRemoveLock) {
- waitForUserRemovalLocked(testUser.id);
- }
assertThat(hasUser(testUser.id)).isFalse();
}
@@ -540,12 +518,12 @@
@Test
public void testRemoveUserWhenPossible_nonCurrentUserRemoved() throws Exception {
final UserInfo user1 = createUser("User 1", /* flags= */ 0);
- synchronized (mUserRemoveLock) {
+
+ runThenWaitForUserRemoval(() -> {
assertThat(mUserManager.removeUserWhenPossible(user1.getUserHandle(),
/* overrideDevicePolicy= */ false))
- .isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
- waitForUserRemovalLocked(user1.id);
- }
+ .isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
+ }, user1.id); // wait for user removal
assertThat(hasUser(user1.id)).isFalse();
}
@@ -562,12 +540,12 @@
final UserInfo workProfileUser = createProfileForUser("Work Profile user",
UserManager.USER_TYPE_PROFILE_MANAGED,
parentUser.id);
- synchronized (mUserRemoveLock) {
+
+ runThenWaitForUserRemoval(() -> {
assertThat(mUserManager.removeUserWhenPossible(parentUser.getUserHandle(),
/* overrideDevicePolicy= */ false))
.isEqualTo(UserManager.REMOVE_RESULT_REMOVED);
- waitForUserRemovalLocked(parentUser.id);
- }
+ }, parentUser.id); // wait for user removal
assertThat(hasUser(parentUser.id)).isFalse();
assertThat(hasUser(cloneProfileUser.id)).isFalse();
@@ -1298,9 +1276,7 @@
UserInfo user = mUserManager.createUser(userName, 0);
if (user != null) {
created.incrementAndGet();
- synchronized (mUserRemoveLock) {
- usersToRemove.add(user.id);
- }
+ mUsersToRemove.add(user.id);
}
});
}
@@ -1462,40 +1438,41 @@
}, () -> fail("Could not complete switching to user " + userId));
}
- private void removeUser(UserHandle user) {
- synchronized (mUserRemoveLock) {
- mUserManager.removeUser(user);
- waitForUserRemovalLocked(user.getIdentifier());
- }
+ private void removeUser(UserHandle userHandle) {
+ runThenWaitForUserRemoval(
+ () -> mUserManager.removeUser(userHandle),
+ userHandle == null ? UserHandle.USER_NULL : userHandle.getIdentifier()
+ );
}
private void removeUser(int userId) {
- synchronized (mUserRemoveLock) {
- mUserManager.removeUser(userId);
- waitForUserRemovalLocked(userId);
- }
+ runThenWaitForUserRemoval(
+ () -> mUserManager.removeUser(userId),
+ userId
+ );
}
- @GuardedBy("mUserRemoveLock")
- private void waitForUserRemovalLocked(int userId) {
- long time = System.currentTimeMillis();
- while (mUserManager.getUserInfo(userId) != null) {
- try {
- mUserRemoveLock.wait(REMOVE_CHECK_INTERVAL_MILLIS);
- } catch (InterruptedException ie) {
- Thread.currentThread().interrupt();
- return;
- }
- if (System.currentTimeMillis() - time > REMOVE_TIMEOUT_MILLIS) {
- fail("Timeout waiting for removeUser. userId = " + userId);
- }
+ private void runThenWaitForUserRemoval(Runnable runnable, int userIdToWaitUntilDeleted) {
+ Function<Intent, Boolean> checker = intent -> {
+ UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
+ return userHandle != null && userHandle.getIdentifier() == userIdToWaitUntilDeleted;
+ };
+
+ BlockingBroadcastReceiver blockingBroadcastReceiver = BlockingBroadcastReceiver.create(
+ mContext, Intent.ACTION_USER_REMOVED, checker);
+
+ blockingBroadcastReceiver.register();
+
+ try (blockingBroadcastReceiver) {
+ runnable.run();
}
+ mUsersToRemove.remove(userIdToWaitUntilDeleted);
}
private UserInfo createUser(String name, int flags) {
UserInfo user = mUserManager.createUser(name, flags);
if (user != null) {
- usersToRemove.add(user.id);
+ mUsersToRemove.add(user.id);
}
return user;
}
@@ -1503,7 +1480,7 @@
private UserInfo createUser(String name, String userType, int flags) {
UserInfo user = mUserManager.createUser(name, userType, flags);
if (user != null) {
- usersToRemove.add(user.id);
+ mUsersToRemove.add(user.id);
}
return user;
}
@@ -1517,7 +1494,7 @@
UserInfo profile = mUserManager.createProfileForUser(
name, userType, 0, userHandle, disallowedPackages);
if (profile != null) {
- usersToRemove.add(profile.id);
+ mUsersToRemove.add(profile.id);
}
return profile;
}
@@ -1527,7 +1504,7 @@
UserInfo profile = mUserManager.createProfileForUserEvenWhenDisallowed(
name, userType, 0, userHandle, null);
if (profile != null) {
- usersToRemove.add(profile.id);
+ mUsersToRemove.add(profile.id);
}
return profile;
}
@@ -1535,7 +1512,7 @@
private UserInfo createRestrictedProfile(String name) {
UserInfo profile = mUserManager.createRestrictedProfile(name);
if (profile != null) {
- usersToRemove.add(profile.id);
+ mUsersToRemove.add(profile.id);
}
return profile;
}
diff --git a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
index 261156611..7fac9b6 100644
--- a/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/DeviceStateProviderImplTest.java
@@ -35,6 +35,7 @@
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
+import android.os.PowerManager;
import androidx.annotation.NonNull;
@@ -312,6 +313,14 @@
+ " </sensor>\n"
+ " </conditions>\n"
+ " </device-state>\n"
+ + " <device-state>\n"
+ + " <identifier>4</identifier>\n"
+ + " <name>THERMAL_TEST</name>\n"
+ + " <flags>\n"
+ + " <flag>FLAG_EMULATED_ONLY</flag>\n"
+ + " <flag>FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL</flag>\n"
+ + " </flags>\n"
+ + " </device-state>\n"
+ "</device-state-config>\n";
DeviceStateProviderImpl.ReadableConfig config = new TestReadableConfig(configString);
return DeviceStateProviderImpl.createFromConfig(mContext,
@@ -332,7 +341,10 @@
new DeviceState[]{
new DeviceState(1, "CLOSED", 0 /* flags */),
new DeviceState(2, "HALF_OPENED", 0 /* flags */),
- new DeviceState(3, "OPENED", 0 /* flags */) },
+ new DeviceState(3, "OPENED", 0 /* flags */),
+ new DeviceState(4, "THERMAL_TEST",
+ DeviceState.FLAG_EMULATED_ONLY
+ | DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL) },
mDeviceStateArrayCaptor.getValue());
// onStateChanged() should not be called because the provider has not yet been notified of
// the initial sensor state.
@@ -376,6 +388,57 @@
}
@Test
+ public void test_flagDisableWhenThermalStatusCritical() throws Exception {
+ Sensor sensor = newSensor("sensor", Sensor.STRING_TYPE_HINGE_ANGLE);
+ when(mSensorManager.getSensorList(anyInt())).thenReturn(List.of(sensor));
+ DeviceStateProviderImpl provider = create_sensorBasedProvider(sensor);
+
+ provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_LIGHT);
+ DeviceStateProvider.Listener listener = mock(DeviceStateProvider.Listener.class);
+ provider.setListener(listener);
+
+ verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+ assertArrayEquals(
+ new DeviceState[]{
+ new DeviceState(1, "CLOSED", 0 /* flags */),
+ new DeviceState(2, "HALF_OPENED", 0 /* flags */),
+ new DeviceState(3, "OPENED", 0 /* flags */),
+ new DeviceState(4, "THERMAL_TEST",
+ DeviceState.FLAG_EMULATED_ONLY
+ | DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL) },
+ mDeviceStateArrayCaptor.getValue());
+ Mockito.clearInvocations(listener);
+
+ provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_MODERATE);
+ verify(listener, never()).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+ Mockito.clearInvocations(listener);
+
+ // The THERMAL_TEST state should be disabled.
+ provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_CRITICAL);
+ verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+ assertArrayEquals(
+ new DeviceState[]{
+ new DeviceState(1, "CLOSED", 0 /* flags */),
+ new DeviceState(2, "HALF_OPENED", 0 /* flags */),
+ new DeviceState(3, "OPENED", 0 /* flags */) },
+ mDeviceStateArrayCaptor.getValue());
+ Mockito.clearInvocations(listener);
+
+ // The THERMAL_TEST state should be re-enabled.
+ provider.onThermalStatusChanged(PowerManager.THERMAL_STATUS_LIGHT);
+ verify(listener).onSupportedDeviceStatesChanged(mDeviceStateArrayCaptor.capture());
+ assertArrayEquals(
+ new DeviceState[]{
+ new DeviceState(1, "CLOSED", 0 /* flags */),
+ new DeviceState(2, "HALF_OPENED", 0 /* flags */),
+ new DeviceState(3, "OPENED", 0 /* flags */),
+ new DeviceState(4, "THERMAL_TEST",
+ DeviceState.FLAG_EMULATED_ONLY
+ | DeviceState.FLAG_DISABLE_WHEN_THERMAL_STATUS_CRITICAL) },
+ mDeviceStateArrayCaptor.getValue());
+ }
+
+ @Test
public void test_invalidSensorValues() throws Exception {
// onStateChanged() should not be triggered by invalid sensor values.
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
index c2556e9..34e45c2 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/CpuWakeupStatsTest.java
@@ -25,6 +25,7 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.os.Handler;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -35,6 +36,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.util.HashSet;
import java.util.Set;
@@ -55,12 +57,13 @@
private static final int TEST_UID_5 = 76421423;
private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private final Handler mHandler = Mockito.mock(Handler.class);
private final ThreadLocalRandom mRandom = ThreadLocalRandom.current();
@Test
public void removesOldWakeups() {
// The xml resource doesn't matter for this test.
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_1, mHandler);
final Set<Long> timestamps = new HashSet<>();
final long firstWakeup = 453192;
@@ -88,7 +91,7 @@
@Test
public void alarmIrqAttributionSolo() {
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 12423121;
obj.noteWakeupTimeAndReason(wakeupTime, 1, KERNEL_REASON_ALARM_IRQ);
@@ -113,7 +116,7 @@
@Test
public void alarmIrqAttributionCombined() {
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 92123210;
obj.noteWakeupTimeAndReason(wakeupTime, 4,
@@ -143,7 +146,7 @@
@Test
public void unknownIrqAttribution() {
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 92123410;
obj.noteWakeupTimeAndReason(wakeupTime, 24, KERNEL_REASON_UNKNOWN_IRQ);
@@ -163,7 +166,7 @@
@Test
public void unknownAttribution() {
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
final long wakeupTime = 72123210;
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNKNOWN);
@@ -178,7 +181,7 @@
@Test
public void unsupportedAttribution() {
- final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3);
+ final CpuWakeupStats obj = new CpuWakeupStats(sContext, R.xml.irq_device_map_3, mHandler);
long wakeupTime = 970934;
obj.noteWakeupTimeAndReason(wakeupTime, 34, KERNEL_REASON_UNSUPPORTED);
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
index d059472..2e647c4 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MobileRadioPowerCalculatorTest.java
@@ -602,6 +602,8 @@
stats.noteNetworkInterfaceForTransports("cellular",
new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+ stats.notePhoneOnLocked(9800, 9800);
+
// Note application network activity
NetworkStats networkStats = new NetworkStats(10000, 1)
.addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
@@ -614,27 +616,34 @@
mStatsRule.setTime(12_000, 12_000);
- MobileRadioPowerCalculator calculator =
+ MobileRadioPowerCalculator mobileRadioPowerCalculator =
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
-
- mStatsRule.apply(calculator);
+ PhonePowerCalculator phonePowerCalculator =
+ new PhonePowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator);
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
// 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
+ // 1800ms data duration / 2000 total duration * 2.77778 mAh = 2.5
+ // 200ms phone on duration / 2000 total duration * 2.77778 mAh = 0.27777
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.77778);
+ .isWithin(PRECISION).of(2.5);
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isWithin(PRECISION).of(0.27778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(1.53934);
+ .isWithin(PRECISION).of(1.38541);
assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(1.53934);
+ .isWithin(PRECISION).of(1.38541);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
}
@@ -649,6 +658,9 @@
.initMeasuredEnergyStatsLocked();
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+ stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1,
+ 0, 0);
+
// Scan for a cell
stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
TelephonyManager.SIM_STATE_READY,
@@ -686,6 +698,9 @@
stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
+
+ stats.notePhoneOnLocked(9000, 9000);
+
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
@@ -732,16 +747,24 @@
mStatsRule.setTime(10_000, 10_000);
- MobileRadioPowerCalculator calculator =
+ MobileRadioPowerCalculator mobileRadioPowerCalculator =
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
-
- mStatsRule.apply(calculator);
+ PhonePowerCalculator phonePowerCalculator =
+ new PhonePowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator);
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
+ // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
+ // 9000ms data duration / 10000 total duration * 2.77778 mAh = 2.5
+ // 1000ms phone on duration / 10000 total duration * 2.77778 mAh = 0.27777
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.77778);
+ .isWithin(PRECISION).of(2.5);
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isWithin(PRECISION).of(0.27778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
// CDMA2000 [Tx0, Tx1, Tx2, Tx3, Tx4, Rx] drain * duration
// [720, 1080, 1440, 1800, 2160, 1440] mA . [10, 11, 12, 13, 14, 15] ms = 111600 mA-ms
@@ -767,10 +790,10 @@
// _________________
// = 5177753 mA-ms estimated total consumption
//
- // 2.77778 mA-h measured total consumption * 3957753 / 5177753 = 2.123268 mA-h
+ // 2.5 mA-h measured total consumption * 3957753 / 5177753 = 1.91094 mA-h
BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.123268);
+ .isWithin(PRECISION).of(1.91094);
assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
@@ -791,17 +814,17 @@
// 3333768 * 133.33333 / 204.44444 = 2174196.52174 mA-ms App 1 Tx Power Consumption
//
// Total App Power consumption * Ratio of App 1 / Total Estimated Power Consumption
- // 2.123268 * (467988.75 + 2174196.52174) / 3957753 = 1.41749 App 1 Power Consumption
+ // 1.91094 * (467988.75 + 2174196.52174) / 3957753 = 1.27574 App 1 Power Consumption
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(1.41749);
+ .isWithin(PRECISION).of(1.27574);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
// Rest should go to the other app
UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(0.705778);
+ .isWithin(PRECISION).of(0.63520);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
}
@@ -814,6 +837,9 @@
.initMeasuredEnergyStatsLocked();
BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+ stats.noteMobileRadioPowerStateLocked(DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 0, -1,
+ 0, 0);
+
// Scan for a cell
stats.notePhoneStateLocked(ServiceState.STATE_OUT_OF_SERVICE,
TelephonyManager.SIM_STATE_READY,
@@ -851,6 +877,9 @@
stats.notePhoneSignalStrengthLocked(signalStrength, 8333, 8333);
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_MODERATE);
stats.notePhoneSignalStrengthLocked(signalStrength, 8666, 8666);
+
+ stats.notePhoneOnLocked(9000, 9000);
+
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
stats.notePhoneSignalStrengthLocked(signalStrength, 9110, 9110);
when(gsmSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GREAT);
@@ -868,30 +897,38 @@
mStatsRule.setTime(12_000, 12_000);
- MobileRadioPowerCalculator calculator =
- new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ MobileRadioPowerCalculator mobileRadioPowerCalculator =
+ new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
+ PhonePowerCalculator phonePowerCalculator =
+ new PhonePowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator);
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
// 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
+ // 9000ms data duration / 10000 total duration * 2.77778 mAh = 2.5
+ // 1000ms phone on duration / 10000 total duration * 2.77778 mAh = 0.27777
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.77778);
+ .isWithin(PRECISION).of(2.5);
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isWithin(PRECISION).of(0.27778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
// Estimated Rx/Tx modem consumption = 0.94 mAh
// Estimated total modem consumption = 1.27888 mAh
- // 2.77778 * 0.94 / 1.27888 = 2.04170 mAh
+ // 2.5 * 0.94 / 1.27888 = 1.83754 mAh
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.04170);
+ .isWithin(PRECISION).of(1.83754);
assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.04170);
+ .isWithin(PRECISION).of(1.83754);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION);
}
diff --git a/services/tests/voiceinteractiontests/Android.bp b/services/tests/voiceinteractiontests/Android.bp
new file mode 100644
index 0000000..9ca2876
--- /dev/null
+++ b/services/tests/voiceinteractiontests/Android.bp
@@ -0,0 +1,60 @@
+// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "FrameworksVoiceInteractionTests",
+ defaults: [
+ "modules-utils-testable-device-config-defaults",
+ ],
+
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.runner",
+ "androidx.test.ext.truth",
+ "mockito-target-extended-minus-junit4",
+ "platform-test-annotations",
+ "services.core",
+ "services.voiceinteraction",
+ "servicestests-core-utils",
+ "servicestests-utils-mockito-extended",
+ "truth-prebuilt",
+ ],
+
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/services/tests/voiceinteractiontests/AndroidManifest.xml b/services/tests/voiceinteractiontests/AndroidManifest.xml
new file mode 100644
index 0000000..ce76a51
--- /dev/null
+++ b/services/tests/voiceinteractiontests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.voiceinteractiontests">
+
+ <application android:testOnly="true"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.voiceinteractiontests"
+ android:label="Frameworks Voice Interaction Services Tests" />
+
+</manifest>
diff --git a/services/tests/voiceinteractiontests/AndroidTest.xml b/services/tests/voiceinteractiontests/AndroidTest.xml
new file mode 100644
index 0000000..ce48633
--- /dev/null
+++ b/services/tests/voiceinteractiontests/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Frameworks Voice Interaction Services Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="FrameworksVoiceInteractionTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="FrameworksVoiceInteractionTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.voiceinteractiontests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/services/tests/voiceinteractiontests/OWNERS b/services/tests/voiceinteractiontests/OWNERS
new file mode 100644
index 0000000..86d392e
--- /dev/null
+++ b/services/tests/voiceinteractiontests/OWNERS
@@ -0,0 +1 @@
+include /services/voiceinteraction/OWNERS
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/HotwordAudioStreamCopierTest.java b/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/HotwordAudioStreamCopierTest.java
new file mode 100644
index 0000000..8f35c11
--- /dev/null
+++ b/services/tests/voiceinteractiontests/src/com/android/server/voiceinteraction/HotwordAudioStreamCopierTest.java
@@ -0,0 +1,296 @@
+/*
+ * 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.voiceinteraction;
+
+import static android.service.voice.HotwordAudioStream.KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES;
+
+import static com.android.server.voiceinteraction.HotwordAudioStreamCopier.DEFAULT_COPY_BUFFER_LENGTH_BYTES;
+import static com.android.server.voiceinteraction.HotwordAudioStreamCopier.MAX_COPY_BUFFER_LENGTH_BYTES;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+
+import android.app.AppOpsManager;
+import android.media.AudioFormat;
+import android.media.MediaSyncEvent;
+import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
+import android.platform.test.annotations.Presubmit;
+import android.service.voice.HotwordAudioStream;
+import android.service.voice.HotwordDetectedResult;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.jetbrains.annotations.NotNull;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class HotwordAudioStreamCopierTest {
+
+ private static final int DETECTOR_TYPE = 1;
+ private static final int VOICE_INTERACTOR_UID = 999;
+ private static final String VOICE_INTERACTOR_PACKAGE_NAME = "VIPackageName";
+ private static final String VOICE_INTERACTOR_ATTRIBUTION_TAG = "VIAttributionTag";
+ private static final AudioFormat FAKE_AUDIO_FORMAT =
+ new AudioFormat.Builder()
+ .setSampleRate(32000)
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO).build();
+
+ private HotwordAudioStreamCopier mCopier;
+ private AppOpsManager mAppOpsManager;
+
+ @Before
+ public void setUp() {
+ mAppOpsManager = mock(AppOpsManager.class);
+ mCopier = new HotwordAudioStreamCopier(mAppOpsManager, DETECTOR_TYPE, VOICE_INTERACTOR_UID,
+ VOICE_INTERACTOR_PACKAGE_NAME, VOICE_INTERACTOR_ATTRIBUTION_TAG);
+ }
+
+ @Test
+ public void testDefaultCopyBufferLength() throws Exception {
+ ParcelFileDescriptor[] fakeAudioStreamPipe = ParcelFileDescriptor.createPipe();
+ try {
+ // There is no copy buffer length is specified in the metadata.
+ // HotwordAudioStreamCopier should use the default copy buffer length.
+ List<HotwordAudioStream> originalAudioStreams = new ArrayList<>();
+ HotwordAudioStream audioStream = new HotwordAudioStream.Builder(FAKE_AUDIO_FORMAT,
+ fakeAudioStreamPipe[0]).build();
+ originalAudioStreams.add(audioStream);
+ HotwordDetectedResult originalResult = buildHotwordDetectedResultWithStreams(
+ originalAudioStreams);
+
+ HotwordDetectedResult managedResult = mCopier.startCopyingAudioStreams(
+ originalResult);
+ List<HotwordAudioStream> managedAudioStreams = managedResult.getAudioStreams();
+ assertThat(managedAudioStreams.size()).isEqualTo(1);
+
+ ParcelFileDescriptor readFd =
+ managedAudioStreams.get(0).getAudioStreamParcelFileDescriptor();
+ ParcelFileDescriptor writeFd = fakeAudioStreamPipe[1];
+ verifyCopyBufferLength(DEFAULT_COPY_BUFFER_LENGTH_BYTES, readFd, writeFd);
+ } finally {
+ closeAudioStreamPipe(fakeAudioStreamPipe);
+ }
+ }
+
+ @Test
+ public void testCustomCopyBufferLength() throws Exception {
+ List<ParcelFileDescriptor[]> fakeAudioStreamPipes = new ArrayList<>();
+ try {
+ // We create 4 audio streams, with various small prime values specified in the metadata.
+ // HotwordAudioStreamCopier reads data in chunks the size of the buffer. In
+ // verifyCopyBufferLength(), we check if the number of bytes read from the copied stream
+ // is a multiple of the buffer length.
+ //
+ // By using prime numbers, this ensures that HotwordAudioStreamCopier is reading the
+ // correct buffer length for the corresponding stream, since multiples of different
+ // primes cannot be equal. A small number helps ensure that the test reads the copied
+ // stream before HotwordAudioStreamCopier can copy the entire source stream (which has
+ // a large size).
+ int[] copyBufferLengths = new int[]{2, 3, 5, 7};
+ List<HotwordAudioStream> originalAudioStreams = new ArrayList<>();
+ for (int i = 0; i < copyBufferLengths.length; i++) {
+ ParcelFileDescriptor[] fakeAudioStreamPipe = ParcelFileDescriptor.createPipe();
+ fakeAudioStreamPipes.add(fakeAudioStreamPipe);
+ HotwordAudioStream audioStream = new HotwordAudioStream.Builder(FAKE_AUDIO_FORMAT,
+ fakeAudioStreamPipe[0]).build();
+ audioStream.getMetadata().putInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES,
+ copyBufferLengths[i]);
+ originalAudioStreams.add(audioStream);
+ }
+ HotwordDetectedResult originalResult = buildHotwordDetectedResultWithStreams(
+ originalAudioStreams);
+
+ HotwordDetectedResult managedResult = mCopier.startCopyingAudioStreams(
+ originalResult);
+ List<HotwordAudioStream> managedAudioStreams = managedResult.getAudioStreams();
+ assertThat(managedAudioStreams.size()).isEqualTo(copyBufferLengths.length);
+
+ for (int i = 0; i < copyBufferLengths.length; i++) {
+ ParcelFileDescriptor readFd =
+ managedAudioStreams.get(i).getAudioStreamParcelFileDescriptor();
+ ParcelFileDescriptor writeFd = fakeAudioStreamPipes.get(i)[1];
+ verifyCopyBufferLength(copyBufferLengths[i], readFd, writeFd);
+ }
+ } finally {
+ for (ParcelFileDescriptor[] fakeAudioStreamPipe : fakeAudioStreamPipes) {
+ closeAudioStreamPipe(fakeAudioStreamPipe);
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidCopyBufferLength_NonPositive() throws Exception {
+ ParcelFileDescriptor[] fakeAudioStreamPipe = ParcelFileDescriptor.createPipe();
+ try {
+ // An invalid copy buffer length (non-positive) is specified in the metadata.
+ // HotwordAudioStreamCopier should use the default copy buffer length.
+ List<HotwordAudioStream> originalAudioStreams = new ArrayList<>();
+ HotwordAudioStream audioStream = new HotwordAudioStream.Builder(FAKE_AUDIO_FORMAT,
+ fakeAudioStreamPipe[0]).build();
+ audioStream.getMetadata().putInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES, 0);
+ originalAudioStreams.add(audioStream);
+ HotwordDetectedResult originalResult = buildHotwordDetectedResultWithStreams(
+ originalAudioStreams);
+
+ HotwordDetectedResult managedResult = mCopier.startCopyingAudioStreams(
+ originalResult);
+ List<HotwordAudioStream> managedAudioStreams = managedResult.getAudioStreams();
+ assertThat(managedAudioStreams.size()).isEqualTo(1);
+
+ ParcelFileDescriptor readFd =
+ managedAudioStreams.get(0).getAudioStreamParcelFileDescriptor();
+ ParcelFileDescriptor writeFd = fakeAudioStreamPipe[1];
+ verifyCopyBufferLength(DEFAULT_COPY_BUFFER_LENGTH_BYTES, readFd, writeFd);
+ } finally {
+ closeAudioStreamPipe(fakeAudioStreamPipe);
+ }
+ }
+
+ @Test
+ public void testInvalidCopyBufferLength_ExceedsMaximum() throws Exception {
+ ParcelFileDescriptor[] fakeAudioStreamPipe = ParcelFileDescriptor.createPipe();
+ try {
+ // An invalid copy buffer length (exceeds the maximum) is specified in the metadata.
+ // HotwordAudioStreamCopier should use the default copy buffer length.
+ List<HotwordAudioStream> originalAudioStreams = new ArrayList<>();
+ HotwordAudioStream audioStream = new HotwordAudioStream.Builder(FAKE_AUDIO_FORMAT,
+ fakeAudioStreamPipe[0]).build();
+ audioStream.getMetadata().putInt(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES,
+ MAX_COPY_BUFFER_LENGTH_BYTES + 1);
+ originalAudioStreams.add(audioStream);
+ HotwordDetectedResult originalResult = buildHotwordDetectedResultWithStreams(
+ originalAudioStreams);
+
+ HotwordDetectedResult managedResult = mCopier.startCopyingAudioStreams(
+ originalResult);
+ List<HotwordAudioStream> managedAudioStreams = managedResult.getAudioStreams();
+ assertThat(managedAudioStreams.size()).isEqualTo(1);
+
+ ParcelFileDescriptor readFd =
+ managedAudioStreams.get(0).getAudioStreamParcelFileDescriptor();
+ ParcelFileDescriptor writeFd = fakeAudioStreamPipe[1];
+ verifyCopyBufferLength(DEFAULT_COPY_BUFFER_LENGTH_BYTES, readFd, writeFd);
+ } finally {
+ closeAudioStreamPipe(fakeAudioStreamPipe);
+ }
+ }
+
+ @Test
+ public void testInvalidCopyBufferLength_NotAnInt() throws Exception {
+ ParcelFileDescriptor[] fakeAudioStreamPipe = ParcelFileDescriptor.createPipe();
+ try {
+ // An invalid copy buffer length (not an int) is specified in the metadata.
+ // HotwordAudioStreamCopier should use the default copy buffer length.
+ List<HotwordAudioStream> originalAudioStreams = new ArrayList<>();
+ HotwordAudioStream audioStream = new HotwordAudioStream.Builder(FAKE_AUDIO_FORMAT,
+ fakeAudioStreamPipe[0]).build();
+ audioStream.getMetadata().putString(KEY_AUDIO_STREAM_COPY_BUFFER_LENGTH_BYTES,
+ "Not an int");
+ originalAudioStreams.add(audioStream);
+ HotwordDetectedResult originalResult = buildHotwordDetectedResultWithStreams(
+ originalAudioStreams);
+
+ HotwordDetectedResult managedResult = mCopier.startCopyingAudioStreams(
+ originalResult);
+ List<HotwordAudioStream> managedAudioStreams = managedResult.getAudioStreams();
+ assertThat(managedAudioStreams.size()).isEqualTo(1);
+
+ ParcelFileDescriptor readFd =
+ managedAudioStreams.get(0).getAudioStreamParcelFileDescriptor();
+ ParcelFileDescriptor writeFd = fakeAudioStreamPipe[1];
+ verifyCopyBufferLength(DEFAULT_COPY_BUFFER_LENGTH_BYTES, readFd, writeFd);
+ } finally {
+ closeAudioStreamPipe(fakeAudioStreamPipe);
+ }
+ }
+
+ private void verifyCopyBufferLength(int expectedCopyBufferLength, ParcelFileDescriptor readFd,
+ ParcelFileDescriptor writeFd) throws IOException {
+ byte[] bytesToRepeat = new byte[]{99};
+ try (InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(readFd);
+ OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(writeFd)) {
+ writeToFakeAudioStreamPipe(os, bytesToRepeat, MAX_COPY_BUFFER_LENGTH_BYTES);
+ byte[] actualBytesRead = new byte[MAX_COPY_BUFFER_LENGTH_BYTES];
+ int numBytesRead = is.read(actualBytesRead);
+
+ // HotwordAudioStreamCopier reads data in chunks the size of the buffer. We write MAX
+ // bytes but the actual number of bytes read from the copied stream should be a
+ // multiple of the buffer length.
+ assertThat(numBytesRead % expectedCopyBufferLength).isEqualTo(0);
+ }
+ }
+
+ @NotNull
+ private static HotwordDetectedResult buildHotwordDetectedResultWithStreams(
+ List<HotwordAudioStream> audioStreams) {
+ return new HotwordDetectedResult.Builder()
+ .setConfidenceLevel(HotwordDetectedResult.CONFIDENCE_LEVEL_LOW)
+ .setMediaSyncEvent(MediaSyncEvent.createEvent(
+ MediaSyncEvent.SYNC_EVENT_PRESENTATION_COMPLETE))
+ .setHotwordOffsetMillis(100)
+ .setHotwordDurationMillis(1000)
+ .setAudioChannel(1)
+ .setHotwordDetectionPersonalized(true)
+ .setScore(100)
+ .setPersonalizedScore(100)
+ .setHotwordPhraseId(1)
+ .setAudioStreams(audioStreams)
+ .setExtras(new PersistableBundle())
+ .build();
+ }
+
+ private static void writeToFakeAudioStreamPipe(OutputStream writeOutputStream,
+ byte[] bytesToRepeat, int totalBytesToWrite) throws IOException {
+ // Create the fake stream buffer, consisting of bytesToRepeat, repeated as many times as
+ // needed to get to totalBytesToWrite.
+ byte[] fakeAudioData = new byte[totalBytesToWrite];
+ int bytesWritten = 0;
+ while (bytesWritten + bytesToRepeat.length <= totalBytesToWrite) {
+ System.arraycopy(bytesToRepeat, 0, fakeAudioData, bytesWritten, bytesToRepeat.length);
+ bytesWritten += bytesToRepeat.length;
+ }
+ if (bytesWritten < totalBytesToWrite) {
+ int bytesLeft = totalBytesToWrite - bytesWritten;
+ System.arraycopy(bytesToRepeat, 0, fakeAudioData, bytesWritten, bytesLeft);
+ }
+
+ writeOutputStream.write(fakeAudioData);
+ }
+
+ private static void closeAudioStreamPipe(ParcelFileDescriptor[] parcelFileDescriptors)
+ throws IOException {
+ if (parcelFileDescriptors != null) {
+ parcelFileDescriptors[0].close();
+ parcelFileDescriptors[1].close();
+ }
+ }
+
+}
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 e02863e..e663245 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2315,7 +2315,7 @@
.build();
final ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params);
final ActivityRecord activity = new ActivityBuilder(mAtm)
- .setLaunchIntoPipActivityOptions(opts)
+ .setActivityOptions(opts)
.build();
// Verify the pictureInPictureArgs is set on the new Activity
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ca28558..1deb58e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -71,6 +71,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -749,16 +750,15 @@
}
/**
- * This test ensures that supported usecases aren't aborted when background starts are
- * disallowed. Each scenarios tests one condition that makes them supported in isolation. In
- * this case the real calling process (pending intent) has a visible window.
+ * The sending app has a visible window, but does not (by default) allow the pending intent to
+ * start the background activity.
*/
@Test
- public void
- testBackgroundActivityStartsDisallowed_realCallingUidHasVisibleWindowNotAborted() {
+ public void testBackgroundActivityStartsDisallowed_realCallingUidHasVisibleWindowAborted() {
doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
+
runAndVerifyBackgroundActivityStartsSubtest(
- "disallowed_realCallingUidHasVisibleWindow_notAborted", false,
+ "disallowed_realCallingUidHasVisibleWindow_abortedInU", true,
UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
UNIMPORTANT_UID2, true, PROCESS_STATE_BOUND_TOP,
false, false, false, false, false, false);
@@ -1507,7 +1507,7 @@
.build();
final ActivityOptions opts = ActivityOptions.makeLaunchIntoPip(params);
ActivityRecord targetRecord = new ActivityBuilder(mAtm)
- .setLaunchIntoPipActivityOptions(opts)
+ .setActivityOptions(opts)
.build();
// Start the target launch-into-pip activity from a source
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
index eed32d7..bb20244 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
@@ -249,6 +249,19 @@
}
/**
+ * Ensures it updates recent tasks order when the last resumed activity changed.
+ */
+ @Test
+ public void testUpdateRecentTasksForTopResumed() {
+ spyOn(mSupervisor.mRecentTasks);
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = activity.getTask();
+
+ mAtm.setLastResumedActivityUncheckLocked(activity, "test");
+ verify(mSupervisor.mRecentTasks).add(eq(task));
+ }
+
+ /**
* Ensures that a trusted display can launch arbitrary activity and an untrusted display can't.
*/
@Test
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 9a786d4..ee8a988 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -16,8 +16,10 @@
package com.android.server.wm;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.window.BackNavigationInfo.typeToString;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -37,8 +39,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;
@@ -219,6 +223,35 @@
assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(appCallback);
}
+ // TODO (b/259427810) Remove this test when we figure out new API
+ @Test
+ public void backAnimationSkipSharedElementTransition() {
+ // Simulate ActivityOptions#makeSceneTransitionAnimation
+ final Bundle myBundle = new Bundle();
+ myBundle.putInt(ActivityOptions.KEY_ANIM_TYPE, ANIM_SCENE_TRANSITION);
+ myBundle.putParcelable("android:activity.transitionCompleteListener",
+ mock(android.os.ResultReceiver.class));
+ final ActivityOptions options = new ActivityOptions(myBundle);
+
+ final ActivityRecord testActivity = new ActivityBuilder(mAtm)
+ .setCreateTask(true)
+ .setActivityOptions(options)
+ .build();
+ testActivity.info.applicationInfo.privateFlagsExt |=
+ PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK;
+ final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, testActivity,
+ "window");
+ addToWindowMap(window, true);
+ makeWindowVisibleAndDrawn(window);
+ IOnBackInvokedCallback callback = withSystemCallback(testActivity.getTask());
+
+ BackNavigationInfo backNavigationInfo = startBackNavigation();
+ assertTrue(testActivity.mHasSceneTransition);
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+ assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
+ }
+
@Test
public void testUnregisterCallbacksWithSystemCallback()
throws InterruptedException, RemoteException {
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 352e498..3b7b5eb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1931,6 +1931,132 @@
}
@Test
+ public void testDisplayAspectRatioForResizablePortraitApps() {
+ // Set up a display in portrait and ignoring orientation request.
+ int displayWidth = 1400;
+ int displayHeight = 1600;
+ setUpDisplaySizeWithApp(displayWidth, displayHeight);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mWm.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(2f);
+
+ // Enable display aspect ratio to take precedence before
+ // fixedOrientationLetterboxAspectRatio
+ mWm.mLetterboxConfiguration
+ .setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(true);
+
+ // Set up resizable app in portrait
+ prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_PORTRAIT, false /* isUnresizable */);
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
+ // Move activity to split screen which takes half of the screen.
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ organizer.mPrimary.setBounds(0, 0, displayWidth, getExpectedSplitSize(displayHeight));
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
+
+ // App should launch in fixed orientation letterbox.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ // Checking that there is no size compat mode.
+ assertFitted();
+ // Check that the display aspect ratio is used by the app.
+ final float targetMinAspectRatio = 1f * displayHeight / displayWidth;
+ final float delta = 0.01f;
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(mActivity.getBounds()), delta);
+ }
+
+ @Test
+ public void testDisplayAspectRatioForResizableLandscapeApps() {
+ // Set up a display in landscape and ignoring orientation request.
+ int displayWidth = 1600;
+ int displayHeight = 1400;
+ setUpDisplaySizeWithApp(displayWidth, displayHeight);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mWm.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(2f);
+
+ // Enable display aspect ratio to take precedence before
+ // fixedOrientationLetterboxAspectRatio
+ mWm.mLetterboxConfiguration
+ .setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(true);
+
+ // Set up resizable app in landscape
+ prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_LANDSCAPE, false /* isUnresizable */);
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
+ // Move activity to split screen which takes half of the screen.
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(displayWidth), displayHeight);
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
+ assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
+
+ // App should launch in fixed orientation letterbox.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ // Checking that there is no size compat mode.
+ assertFitted();
+ // Check that the display aspect ratio is used by the app.
+ final float targetMinAspectRatio = 1f * displayWidth / displayHeight;
+ final float delta = 0.01f;
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(mActivity.getBounds()), delta);
+ }
+
+ @Test
+ public void testDisplayAspectRatioForUnresizableLandscapeApps() {
+ // Set up a display in portrait and ignoring orientation request.
+ int displayWidth = 1400;
+ int displayHeight = 1600;
+ setUpDisplaySizeWithApp(displayWidth, displayHeight);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);
+ // Enable display aspect ratio to take precedence before
+ // fixedOrientationLetterboxAspectRatio
+ mWm.mLetterboxConfiguration
+ .setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(true);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+
+ // App should launch in fixed orientation letterbox.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ // Checking that there is no size compat mode.
+ assertFitted();
+ // Check that the display aspect ratio is used by the app.
+ final float targetMinAspectRatio = 1f * displayHeight / displayWidth;
+ final float delta = 0.01f;
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(mActivity.getBounds()), delta);
+ }
+
+ @Test
+ public void testDisplayAspectRatioForUnresizablePortraitApps() {
+ // Set up a display in landscape and ignoring orientation request.
+ int displayWidth = 1600;
+ int displayHeight = 1400;
+ setUpDisplaySizeWithApp(displayWidth, displayHeight);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);
+ // Enable display aspect ratio to take precedence before
+ // fixedOrientationLetterboxAspectRatio
+ mWm.mLetterboxConfiguration
+ .setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(true);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ // App should launch in fixed orientation letterbox.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ // Checking that there is no size compat mode.
+ assertFitted();
+ // Check that the display aspect ratio is used by the app.
+ final float targetMinAspectRatio = 1f * displayWidth / displayHeight;
+ final float delta = 0.01f;
+ assertEquals(targetMinAspectRatio, ActivityRecord
+ .computeAspectRatio(mActivity.getBounds()), delta);
+ }
+
+ @Test
public void
testDisplayIgnoreOrientationRequest_orientationLetterboxBecameSizeCompatAfterRotate() {
// Set up a display in landscape and ignoring orientation request.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 0231b46..9018138 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -564,20 +564,29 @@
final WindowProcessController delegateProc = mSystemServicesTestRule.addProcess(
"pkg.delegate", "proc.delegate", 6000 /* pid */, 6000 /* uid */);
doReturn(mock(IBinder.class)).when(delegateProc.getThread()).asBinder();
- final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setVisible(false).build();
+ final Task task = app.getTask();
+ task.setTaskOrganizer(mock(ITaskOrganizer.class), true /* skipTaskAppeared */);
+ app.setVisibleRequested(true);
final TransitionController controller = app.mTransitionController;
final Transition transition = controller.createTransition(TRANSIT_OPEN);
final RemoteTransition remoteTransition = new RemoteTransition(
mock(IRemoteTransition.class));
remoteTransition.setAppThread(delegateProc.getThread());
- transition.collectExistenceChange(app.getTask());
- controller.requestStartTransition(transition, app.getTask(), remoteTransition,
+ transition.collect(app);
+ controller.requestStartTransition(transition, null /* startTask */, remoteTransition,
null /* displayChange */);
testPlayer.startTransition();
+ app.onStartingWindowDrawn();
+ // The task appeared event should be deferred until transition ready.
+ assertFalse(task.taskAppearedReady());
testPlayer.onTransactionReady(app.getSyncTransaction());
+ assertTrue(task.taskAppearedReady());
assertTrue(playerProc.isRunningRemoteTransition());
assertTrue(delegateProc.isRunningRemoteTransition());
assertTrue(controller.mRemotePlayer.reportRunning(delegateProc.getThread()));
+ assertTrue(app.isVisible());
testPlayer.finish();
assertFalse(playerProc.isRunningRemoteTransition());
@@ -1114,6 +1123,14 @@
assertFalse(activity1.isVisible());
assertTrue(activity2.isVisible());
+
+ // The abort should still commit visible-requested to visible.
+ final Transition abortTransition = controller.createTransition(TRANSIT_OPEN);
+ abortTransition.collect(activity1);
+ activity1.setVisibleRequested(true);
+ activity1.setVisible(false);
+ abortTransition.abort();
+ assertTrue(activity1.isVisible());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 4d31414..e5efe05 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -262,6 +262,12 @@
// device form factors.
mAtm.mWindowManager.mLetterboxConfiguration
.setIsSplitScreenAspectRatioForUnresizableAppsEnabled(false);
+ // Ensure aspect ratio for al apps isn't overridden on any device target.
+ // {@link com.android.internal.R.bool
+ // .config_letterboxIsDisplayAspectRatioForFixedOrientationLetterboxEnabled}, may be set on
+ // some device form factors.
+ mAtm.mWindowManager.mLetterboxConfiguration
+ .setIsDisplayAspectRatioEnabledForFixedOrientationLetterbox(false);
checkDeviceSpecificOverridesNotApplied();
}
@@ -276,6 +282,8 @@
mAtm.mWindowManager.mLetterboxConfiguration.resetIsVerticalReachabilityEnabled();
mAtm.mWindowManager.mLetterboxConfiguration
.resetIsSplitScreenAspectRatioForUnresizableAppsEnabled();
+ mAtm.mWindowManager.mLetterboxConfiguration
+ .resetIsDisplayAspectRatioEnabledForFixedOrientationLetterbox();
}
/**
@@ -1016,8 +1024,8 @@
private boolean mOnTop = false;
private ActivityInfo.WindowLayout mWindowLayout;
private boolean mVisible = true;
- private ActivityOptions mLaunchIntoPipOpts;
private String mRequiredDisplayCategory;
+ private ActivityOptions mActivityOpts;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -1153,8 +1161,8 @@
return this;
}
- ActivityBuilder setLaunchIntoPipActivityOptions(ActivityOptions opts) {
- mLaunchIntoPipOpts = opts;
+ ActivityBuilder setActivityOptions(ActivityOptions opts) {
+ mActivityOpts = opts;
return this;
}
@@ -1225,8 +1233,8 @@
}
ActivityOptions options = null;
- if (mLaunchIntoPipOpts != null) {
- options = mLaunchIntoPipOpts;
+ if (mActivityOpts != null) {
+ options = mActivityOpts;
} else if (mLaunchTaskBehind) {
options = ActivityOptions.makeTaskLaunchBehind();
}
diff --git a/services/voiceinteraction/TEST_MAPPING b/services/voiceinteraction/TEST_MAPPING
index af67637..d6c6964 100644
--- a/services/voiceinteraction/TEST_MAPPING
+++ b/services/voiceinteraction/TEST_MAPPING
@@ -31,6 +31,14 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "FrameworksVoiceInteractionTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
index 2bddd74..2413072 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordAudioStreamCopier.java
@@ -36,6 +36,8 @@
import android.service.voice.HotwordDetectedResult;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -60,10 +62,12 @@
private static final String OP_MESSAGE = "Streaming hotword audio to VoiceInteractionService";
private static final String TASK_ID_PREFIX = "HotwordDetectedResult@";
private static final String THREAD_NAME_PREFIX = "Copy-";
+ @VisibleForTesting
+ static final int DEFAULT_COPY_BUFFER_LENGTH_BYTES = 32_768;
// Corresponds to the OS pipe capacity in bytes
- private static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536;
- private static final int DEFAULT_COPY_BUFFER_LENGTH_BYTES = 32_768;
+ @VisibleForTesting
+ static final int MAX_COPY_BUFFER_LENGTH_BYTES = 65_536;
private final AppOpsManager mAppOpsManager;
private final int mDetectorType;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 04c8f8f..127195c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -21,7 +21,7 @@
import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.service.voice.VoiceInteractionService.KEY_SHOW_SESSION_ID;
+import static android.service.voice.VoiceInteractionSession.KEY_SHOW_SESSION_ID;
import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 770a374..315ac67 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -21,6 +21,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.os.Binder;
import android.os.Bundle;
import android.os.OutcomeReceiver;
@@ -45,7 +46,8 @@
* {@link OutcomeReceiver#onError} is called and provides a {@link CallException} that details why
* the operation failed.
*/
-public final class CallControl implements AutoCloseable {
+@SuppressLint("NotCloseable")
+public final class CallControl {
private static final String TAG = CallControl.class.getSimpleName();
private static final String INTERFACE_ERROR_MSG = "Call Control is not available";
private final String mCallId;
@@ -261,17 +263,6 @@
}
/**
- * This method should be called after
- * {@link CallControl#disconnect(DisconnectCause, Executor, OutcomeReceiver)} or
- * {@link CallControl#rejectCall(Executor, OutcomeReceiver)}
- * to destroy all references of this object and avoid memory leaks.
- */
- @Override
- public void close() {
- mRepository.removeCallFromServiceWrapper(mPhoneAccountHandle, mCallId);
- }
-
- /**
* Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
* wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
* response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4656226..6138f67 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -33,6 +33,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
+import android.location.Location;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -1050,6 +1051,13 @@
public static final String EXTRA_CALL_QUALITY_REPORT =
"android.telecom.extra.CALL_QUALITY_REPORT";
+ /**
+ * Key to obtain location as a result of ({@code queryLocationForEmergency} from Bundle
+ * @hide
+ */
+ public static final String EXTRA_KEY_QUERY_LOCATION =
+ "android.telecom.extra.KEY_QUERY_LOCATION";
+
// Flag controlling whether PII is emitted into the logs
private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
@@ -1285,6 +1293,9 @@
public void onConnectionTimeReset(Connection c) {}
public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor,
OutcomeReceiver<Void, CallEndpointException> callback) {}
+ public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {}
}
/**
@@ -3233,6 +3244,36 @@
}
/**
+ * Query the device's location in order to place an Emergency Call.
+ * Only SIM call managers can call this method for Connections representing Emergency calls.
+ * If a previous location query request is not completed, the new location query request will
+ * be rejected and return a QueryLocationException with
+ * {@code QueryLocationException#ERROR_PREVIOUS_REQUEST_EXISTS}
+ *
+ * @param timeoutMillis long: Timeout in millis waiting for query response (MAX:5000, MIN:100).
+ * @param provider String: the location provider name, This value cannot be null.
+ * It is the caller's responsibility to select an enabled provider. The caller
+ * can use {@link android.location.LocationManager#getProviders(boolean)}
+ * to choose one of the enabled providers and pass it in.
+ * @param executor The executor of where the callback will execute.
+ * @param callback The callback to notify the result of queryLocation.
+ */
+ public final void queryLocationForEmergency(
+ @IntRange(from = 100, to = 5000) long timeoutMillis,
+ @NonNull String provider,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
+ if (provider == null || executor == null || callback == null) {
+ throw new IllegalArgumentException("There are arguments that must not be null");
+ }
+ if (timeoutMillis < 100 || timeoutMillis > 5000) {
+ throw new IllegalArgumentException("The timeoutMillis should be min 100, max 5000");
+ }
+ mListeners.forEach((l) ->
+ l.onQueryLocation(this, timeoutMillis, provider, executor, callback));
+ }
+
+ /**
* Notifies this Connection that the {@link #getAudioState()} property has a new value.
*
* @param state The new connection audio state.
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 4d6caf8..773ed70 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -16,6 +16,7 @@
package android.telecom;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -25,6 +26,7 @@
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
+import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -2020,6 +2022,16 @@
mAdapter.requestCallEndpointChange(id, endpoint, executor, callback);
}
}
+
+ @Override
+ public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
+ String id = mIdByConnection.get(c);
+ if (id != null) {
+ mAdapter.queryLocation(id, timeoutMillis, provider, executor, callback);
+ }
+ }
};
/** {@inheritDoc} */
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 39928ef..a7105d3 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -16,6 +16,9 @@
package android.telecom;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.location.Location;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -748,4 +751,45 @@
}
}
}
+
+ /**
+ * Query location information.
+ * Only SIM call managers can call this method for Connections representing Emergency calls.
+ * If the previous request is not completed, the new request will be rejected.
+ *
+ * @param timeoutMillis long: Timeout in millis waiting for query response.
+ * @param provider String: the location provider name, This value cannot be null.
+ * @param executor The executor of where the callback will execute.
+ * @param callback The callback to notify the result of queryLocation.
+ */
+ void queryLocation(String callId, long timeoutMillis, @NonNull String provider,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
+ Log.v(this, "queryLocation: %s %d", callId, timeoutMillis);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.queryLocation(callId, timeoutMillis, provider,
+ new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle result) {
+ super.onReceiveResult(resultCode, result);
+
+ if (resultCode == 1 /* success */) {
+ executor.execute(() -> callback.onResult(result.getParcelable(
+ Connection.EXTRA_KEY_QUERY_LOCATION, Location.class)));
+ } else {
+ executor.execute(() -> callback.onError(result.getParcelable(
+ QueryLocationException.QUERY_LOCATION_ERROR,
+ QueryLocationException.class)));
+ }
+ }
+ },
+ Log.getExternalSession());
+ } catch (RemoteException e) {
+ Log.d(this, "queryLocation: Exception e : " + e);
+ executor.execute(() -> callback.onError(new QueryLocationException(
+ e.getMessage(), QueryLocationException.ERROR_SERVICE_UNAVAILABLE)));
+ }
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index c95e14f..8a59020 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -78,6 +78,7 @@
private static final int MSG_SET_CONFERENCE_STATE = 36;
private static final int MSG_HANDLE_CREATE_CONFERENCE_COMPLETE = 37;
private static final int MSG_SET_CALL_DIRECTION = 38;
+ private static final int MSG_QUERY_LOCATION = 39;
private final IConnectionServiceAdapter mDelegate;
@@ -373,6 +374,18 @@
} finally {
args.recycle();
}
+ break;
+ }
+ case MSG_QUERY_LOCATION: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.queryLocation((String) args.arg1, (long) args.arg2,
+ (String) args.arg3, (ResultReceiver) args.arg4,
+ (Session.Info) args.arg5);
+ } finally {
+ args.recycle();
+ }
+ break;
}
}
}
@@ -699,6 +712,18 @@
ResultReceiver callback, Session.Info sessionInfo) {
// Do nothing
}
+
+ @Override
+ public void queryLocation(String callId, long timeoutMillis, String provider,
+ ResultReceiver callback, Session.Info sessionInfo) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = timeoutMillis;
+ args.arg3 = provider;
+ args.arg4 = callback;
+ args.arg5 = sessionInfo;
+ mHandler.obtainMessage(MSG_QUERY_LOCATION, args).sendToTarget();
+ }
};
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 95a8e16..fd2907c 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -32,8 +32,10 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
/**
* A unified virtual device providing a means of voice (and other) communication on a device.
@@ -148,6 +150,14 @@
private final Object mLock = new Object();
+ // Future used to delay terminating the InCallService before the call disconnect tone
+ // finishes playing.
+ private static Map<String, CompletableFuture<Void>> sDisconnectedToneFutures = new ArrayMap<>();
+
+ // Timeout value to be used to ensure future completion for sDisconnectedToneFutures. This is
+ // set to 4 seconds to account for the exceptional case (TONE_CONGESTION).
+ private static final int DISCONNECTED_TONE_TIMEOUT = 4000;
+
Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) {
mInCallAdapter = adapter;
mCallingPackage = callingPackage;
@@ -456,9 +466,45 @@
}
private void fireCallRemoved(Call call) {
- for (Listener listener : mListeners) {
- listener.onCallRemoved(this, call);
+ String callId = call.internalGetCallId();
+ CompletableFuture<Void> disconnectedToneFuture = initializeDisconnectedToneFuture(callId);
+ // delay the InCallService termination until after the disconnect tone finishes playing
+ disconnectedToneFuture.thenRunAsync(() -> {
+ for (Listener listener : mListeners) {
+ listener.onCallRemoved(this, call);
+ }
+ // clean up the future after
+ sDisconnectedToneFutures.remove(callId);
+ });
+ }
+
+ /**
+ * Initialize disconnect tone future to be used in delaying ICS termination.
+ *
+ * @return CompletableFuture to delay InCallService termination until after the disconnect tone
+ * finishes playing. A timeout of 4s is used to handle the use case when we play
+ * TONE_CONGESTION and to ensure completion so that we don't block the removal of the service.
+ */
+ private CompletableFuture<Void> initializeDisconnectedToneFuture(String callId) {
+ // create the future and map (sDisconnectedToneFutures) it to the corresponding call id
+ CompletableFuture<Void> disconnectedToneFuture = new CompletableFuture<Void>()
+ .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT, TimeUnit.MILLISECONDS);
+ // we should not encounter duplicate insertions since call ids are unique
+ sDisconnectedToneFutures.put(callId, disconnectedToneFuture);
+ return disconnectedToneFuture;
+ }
+
+ /**
+ * Completes disconnected tone future with passed in result.
+ * @hide
+ * @return true if future was completed, false otherwise
+ */
+ public static boolean completeDisconnectedToneFuture(String callId) {
+ if (sDisconnectedToneFutures.containsKey(callId)) {
+ sDisconnectedToneFutures.get(callId).complete(null);
+ return true;
}
+ return false;
}
private void fireCallAudioStateChanged(CallAudioState audioState) {
diff --git a/telecomm/java/android/telecom/QueryLocationException.aidl b/telecomm/java/android/telecom/QueryLocationException.aidl
new file mode 100644
index 0000000..56ac412
--- /dev/null
+++ b/telecomm/java/android/telecom/QueryLocationException.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2022, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom;
+
+/**
+ * {@hide}
+ */
+parcelable QueryLocationException;
\ No newline at end of file
diff --git a/telecomm/java/android/telecom/QueryLocationException.java b/telecomm/java/android/telecom/QueryLocationException.java
new file mode 100644
index 0000000..fd90d1e
--- /dev/null
+++ b/telecomm/java/android/telecom/QueryLocationException.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telecom;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.os.OutcomeReceiver;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * This class represents a set of exceptions that can occur when requesting a
+ * {@link Connection#queryLocationForEmergency(long, String, Executor, OutcomeReceiver)}
+ */
+public final class QueryLocationException extends RuntimeException implements Parcelable {
+ /** @hide */
+ public static final String QUERY_LOCATION_ERROR = "QueryLocationErrorKey";
+
+ /**
+ * The operation was not completed on time.
+ */
+ public static final int ERROR_REQUEST_TIME_OUT = 1;
+ /**
+ * The operation was rejected due to an existing request.
+ */
+ public static final int ERROR_PREVIOUS_REQUEST_EXISTS = 2;
+ /**
+ * The operation has failed because it is not permitted.
+ */
+ public static final int ERROR_NOT_PERMITTED = 3;
+ /**
+ * The operation has failed due to a location query being requested for a non-emergency
+ * connection.
+ */
+ public static final int ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS = 4;
+ /**
+ * The operation has failed due to the service is not available.
+ */
+ public static final int ERROR_SERVICE_UNAVAILABLE = 5;
+ /**
+ * The operation has failed due to an unknown or unspecified error.
+ */
+ public static final int ERROR_UNSPECIFIED = 6;
+
+ private int mCode = ERROR_UNSPECIFIED;
+ private final String mMessage;
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString8(mMessage);
+ dest.writeInt(mCode);
+ }
+ /**
+ * Responsible for creating QueryLocationException objects for deserialized Parcels.
+ */
+ public static final
+ @android.annotation.NonNull Parcelable.Creator<QueryLocationException> CREATOR =
+ new Parcelable.Creator<>() {
+ @Override
+ public QueryLocationException createFromParcel(Parcel source) {
+ return new QueryLocationException(source.readString8(), source.readInt());
+ }
+ @Override
+ public QueryLocationException[] newArray(int size) {
+ return new QueryLocationException[size];
+ }
+ };
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ERROR_REQUEST_TIME_OUT,
+ ERROR_PREVIOUS_REQUEST_EXISTS,
+ ERROR_NOT_PERMITTED,
+ ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS,
+ ERROR_SERVICE_UNAVAILABLE,
+ ERROR_UNSPECIFIED})
+ public @interface QueryLocationErrorCode {}
+ public QueryLocationException(@Nullable String message) {
+ super(getMessage(message, ERROR_UNSPECIFIED));
+ mMessage = message;
+ }
+ public QueryLocationException(@Nullable String message, @QueryLocationErrorCode int code) {
+ super(getMessage(message, code));
+ mCode = code;
+ mMessage = message;
+ }
+ public QueryLocationException(
+ @Nullable String message, @QueryLocationErrorCode int code, @Nullable Throwable cause) {
+ super(getMessage(message, code), cause);
+ mCode = code;
+ mMessage = message;
+ }
+ public @QueryLocationErrorCode int getCode() {
+ return mCode;
+ }
+ private static String getMessage(String message, int code) {
+ StringBuilder builder;
+ if (!TextUtils.isEmpty(message)) {
+ builder = new StringBuilder(message);
+ builder.append(" (code: ");
+ builder.append(code);
+ builder.append(")");
+ return builder.toString();
+ } else {
+ return "code: " + code;
+ }
+ }
+}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 6561732..2fc6a22 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -517,6 +517,12 @@
ResultReceiver callback, Session.Info sessionInfo) {
// Do nothing
}
+
+ @Override
+ public void queryLocation(String callId, long timeoutMillis, String provider,
+ ResultReceiver callback, Session.Info sessionInfo) {
+ // Do nothing
+ }
};
private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 6838fbd..8ac0161 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -139,4 +139,7 @@
void setConferenceState(String callId, boolean isConference, in Session.Info sessionInfo);
void setCallDirection(String callId, int direction, in Session.Info sessionInfo);
+
+ void queryLocation(String callId, long timeoutMillis, String provider,
+ in ResultReceiver callback, in Session.Info sessionInfo);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 92d1e5b..7950351 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -7066,7 +7066,7 @@
* Retry SMS over IMS after this Timer expires
*/
public static final String KEY_SMS_OVER_IMS_SEND_RETRY_DELAY_MILLIS_INT =
- KEY_PREFIX + "sms_rover_ims_send_retry_delay_millis_int";
+ KEY_PREFIX + "sms_over_ims_send_retry_delay_millis_int";
/**
* TR1 Timer Value in milliseconds,
@@ -7510,6 +7510,48 @@
public static final String KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL =
KEY_PREFIX + "prefer_ims_emergency_when_voice_calls_on_cs_bool";
+ /** @hide */
+ @IntDef({
+ VOWIFI_REQUIRES_NONE,
+ VOWIFI_REQUIRES_SETTING_ENABLED,
+ VOWIFI_REQUIRES_VALID_EID,
+ })
+ public @interface VoWiFiRequires {}
+
+ /**
+ * Default value.
+ * If {@link ImsWfc#KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL} is {@code true},
+ * VoWi-Fi emergency call shall be attempted if Wi-Fi network is connected.
+ * Otherwise, it shall be attempted if IMS is registered over Wi-Fi.
+ * @hide
+ */
+ public static final int VOWIFI_REQUIRES_NONE = 0;
+
+ /**
+ * VoWi-Fi emergency call shall be attempted on IMS over Wi-Fi if Wi-Fi network is connected
+ * and Wi-Fi calling setting is enabled. This value is applicable if the value of
+ * {@link ImsWfc#KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL} is {@code true}.
+ * @hide
+ */
+ public static final int VOWIFI_REQUIRES_SETTING_ENABLED = 1;
+
+ /**
+ * VoWi-Fi emergency call shall be attempted on IMS over Wi-Fi if Wi-Fi network is connected
+ * and Wi-Fi calling is activated successfully. This value is applicable if the value of
+ * {@link ImsWfc#KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL} is {@code true}.
+ * @hide
+ */
+ public static final int VOWIFI_REQUIRES_VALID_EID = 2;
+
+ /**
+ * Specifies the condition when emergency call shall be attempted on IMS over Wi-Fi.
+ *
+ * The default value for this key is {@code #VOWIFI_REQUIRES_NONE}.
+ * @hide
+ */
+ public static final String KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT =
+ KEY_PREFIX + "emergency_vowifi_requires_condition_int";
+
/**
* Specifies maximum number of emergency call retries over Wi-Fi.
* This is valid only when {@link #DOMAIN_PS_NON_3GPP} is included in
@@ -7621,7 +7663,8 @@
KEY_PREFIX + "emergency_cdma_preferred_numbers_string_array";
/**
- * Specifies if emergency call shall be attempted on IMS only when VoLTE is enabled.
+ * Specifies if emergency call shall be attempted on IMS over cellular network
+ * only when VoLTE is enabled.
*
* The default value for this key is {@code false}.
* @hide
@@ -7685,6 +7728,7 @@
});
defaults.putBoolean(KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL, false);
+ defaults.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_NONE);
defaults.putInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT, 1);
defaults.putInt(KEY_EMERGENCY_SCAN_TIMER_SEC_INT, 10);
defaults.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_NO_PREFERENCE);
diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java
index ceea94b..eac4d16 100644
--- a/telephony/java/android/telephony/CarrierRestrictionRules.java
+++ b/telephony/java/android/telephony/CarrierRestrictionRules.java
@@ -104,12 +104,15 @@
private int mCarrierRestrictionDefault;
@MultiSimPolicy
private int mMultiSimPolicy;
+ @TelephonyManager.CarrierRestrictionStatus
+ private int mCarrierRestrictionStatus;
private CarrierRestrictionRules() {
mAllowedCarriers = new ArrayList<CarrierIdentifier>();
mExcludedCarriers = new ArrayList<CarrierIdentifier>();
mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED;
mMultiSimPolicy = MULTISIM_POLICY_NONE;
+ mCarrierRestrictionStatus = TelephonyManager.CARRIER_RESTRICTION_STATUS_UNKNOWN;
}
private CarrierRestrictionRules(Parcel in) {
@@ -120,6 +123,7 @@
in.readTypedList(mExcludedCarriers, CarrierIdentifier.CREATOR);
mCarrierRestrictionDefault = in.readInt();
mMultiSimPolicy = in.readInt();
+ mCarrierRestrictionStatus = in.readInt();
}
/**
@@ -289,6 +293,11 @@
return true;
}
+ /** @hide */
+ public int getCarrierRestrictionStatus() {
+ return mCarrierRestrictionStatus;
+ }
+
/**
* {@link Parcelable#writeToParcel}
*/
@@ -298,6 +307,7 @@
out.writeTypedList(mExcludedCarriers);
out.writeInt(mCarrierRestrictionDefault);
out.writeInt(mMultiSimPolicy);
+ out.writeInt(mCarrierRestrictionStatus);
}
/**
@@ -399,5 +409,17 @@
mRules.mMultiSimPolicy = multiSimPolicy;
return this;
}
+
+ /**
+ * Set the device's carrier restriction status
+ *
+ * @param carrierRestrictionStatus device restriction status
+ * @hide
+ */
+ public @NonNull
+ Builder setCarrierRestrictionStatus(int carrierRestrictionStatus) {
+ mRules.mCarrierRestrictionStatus = carrierRestrictionStatus;
+ return this;
+ }
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 913ea9a..83b9098 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -360,6 +360,31 @@
public static final int SRVCC_STATE_HANDOVER_CANCELED = 3;
/**
+ * Convert srvcc handover state to string.
+ *
+ * @param state The srvcc handover state.
+ * @return The srvcc handover state in string format.
+ *
+ * @hide
+ */
+ public static @NonNull String srvccStateToString(int state) {
+ switch (state) {
+ case TelephonyManager.SRVCC_STATE_HANDOVER_NONE:
+ return "NONE";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_STARTED:
+ return "STARTED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED:
+ return "COMPLETED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_FAILED:
+ return "FAILED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED:
+ return "CANCELED";
+ default:
+ return "UNKNOWN(" + state + ")";
+ }
+ }
+
+ /**
* A UICC card identifier used if the device does not support the operation.
* For example, {@link #getCardIdForDefaultEuicc()} returns this value if the device has no
* eUICC, or the eUICC cannot be read.
@@ -13137,6 +13162,81 @@
}
/**
+ * Carrier restriction status value is unknown, in case modem did not provide any
+ * information about carrier restriction status.
+ */
+ public static final int CARRIER_RESTRICTION_STATUS_UNKNOWN = 0;
+
+ /** The device is not restricted to a carrier */
+ public static final int CARRIER_RESTRICTION_STATUS_NOT_RESTRICTED = 1;
+
+ /** The device is restricted to a carrier. */
+ public static final int CARRIER_RESTRICTION_STATUS_RESTRICTED = 2;
+
+ /** The device is restricted to the carrier of the calling application. */
+ public static final int CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER = 3;
+
+ /** @hide */
+ @IntDef(prefix = {"CARRIER_RESTRICTION_STATUS_"}, value = {
+ CARRIER_RESTRICTION_STATUS_UNKNOWN,
+ CARRIER_RESTRICTION_STATUS_NOT_RESTRICTED,
+ CARRIER_RESTRICTION_STATUS_RESTRICTED,
+ CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER
+ })
+
+ public @interface CarrierRestrictionStatus {
+ }
+
+ /**
+ * Get the carrier restriction status of the device.
+ * <p>To fetch the carrier restriction status of the device the calling application needs to be
+ * allowlisted to Android at <a href="https://android.googlesource.com/platform/packages/services/Telephony/+/master/assets/CarrierRestrictionOperatorDetails.json">here</a>.
+ * The calling application also needs the READ_PHONE_STATE permission.
+ * The return value of the API is as follows.
+ * <ul>
+ * <li>return {@link #CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER} if the caller
+ * and the device locked by the network are same</li>
+ * <li>return {@link #CARRIER_RESTRICTION_STATUS_RESTRICTED} if the caller and the
+ * device locked by the network are different</li>
+ * <li>return {@link #CARRIER_RESTRICTION_STATUS_NOT_RESTRICTED} if the device is
+ * not locked</li>
+ * <li>return {@link #CARRIER_RESTRICTION_STATUS_UNKNOWN} if the device locking
+ * state is unavailable or radio does not supports the feature</li>
+ * </ul>
+ *
+ * @param executor The executor on which the result listener will be called.
+ * @param resultListener {@link Consumer} that will be called with the result fetched
+ * from the radio of type {@link CarrierRestrictionStatus}
+ * @throws SecurityException if the caller does not have the required permission/privileges or
+ * if the caller is not pre-registered.
+ */
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public void getCarrierRestrictionStatus(@NonNull Executor executor,
+ @NonNull @CarrierRestrictionStatus
+ Consumer<Integer> resultListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(resultListener);
+
+ IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(@CarrierRestrictionStatus int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> resultListener.accept(result)));
+ }
+ };
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ service.getCarrierRestrictionStatus(internalCallback, getOpPackageName());
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCarrierRestrictionStatus: RemoteException = " + ex);
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Used to enable or disable carrier data by the system based on carrier signalling or
* carrier privileged apps. Different from {@link #setDataEnabled(boolean)} which is linked to
* user settings, carrier data on/off won't affect user settings but will bypass the
@@ -14977,6 +15077,14 @@
@TestApi
public static final int HAL_SERVICE_IMS = 7;
+ /**
+ * HAL service type that supports the HAL APIs implementation of IRadioSatellite
+ * {@link RadioSatelliteProxy}
+ * @hide
+ */
+ @TestApi
+ public static final int HAL_SERVICE_SATELLITE = 8;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"HAL_SERVICE_"},
@@ -14989,6 +15097,7 @@
HAL_SERVICE_SIM,
HAL_SERVICE_VOICE,
HAL_SERVICE_IMS,
+ HAL_SERVICE_SATELLITE
})
public @interface HalService {}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 6970cd5..37a6a7e 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -1688,7 +1688,8 @@
/**
* Notify the framework that an RCS autoconfiguration XML file has been received for
- * provisioning.
+ * provisioning. This API is only valid if the device supports IMS, which can be checked using
+ * {@link PackageManager#hasSystemFeature}.
*
* <p>Requires Permission:
* <ul>
@@ -1926,7 +1927,8 @@
/**
* Reconfiguration triggered by the RCS application. Most likely cause
- * is the 403 forbidden to a HTTP request.
+ * is the 403 forbidden to a HTTP request. This API is only valid if the device supports IMS,
+ * which can be checked using {@link PackageManager#hasSystemFeature}
*
* <p>When this api is called, the RCS configuration for the associated
* subscription will be removed, and the application which has registered
diff --git a/telephony/java/android/telephony/ims/PublishAttributes.java b/telephony/java/android/telephony/ims/PublishAttributes.java
index c4ce6ed..b987f1c 100644
--- a/telephony/java/android/telephony/ims/PublishAttributes.java
+++ b/telephony/java/android/telephony/ims/PublishAttributes.java
@@ -97,14 +97,18 @@
}
/**
+ * Get the current publication state when the publishing state has changed or
+ * the publishing operation has done.
* @return The current publication state. See {@link RcsUceAdapter.PublishState}.
*/
- public int getPublishState() {
+ public @PublishState int getPublishState() {
return mPublishState;
}
/**
- * @return The list of the {@link RcsContactPresenceTuple} sent to the server.
+ * Get the presence tuples from the PIDF on which the publishing was successful.
+ * @return The list of the {@link RcsContactPresenceTuple} sent to the server. If publish is
+ * not successful yet, the value is empty.
*/
public @NonNull List<RcsContactPresenceTuple> getPresenceTuples() {
if (mPresenceTuples == null) {
@@ -114,7 +118,9 @@
}
/**
- * @return The {@link SipDetails} received in response.
+ * Get the SipDetails set in ImsService.
+ * @return The {@link SipDetails} received in response. This value may be null if
+ * the device doesn't support the collection of this information.
*/
public @Nullable SipDetails getSipDetails() {
return mSipDetails;
diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
index 6a6c306..74bac22 100644
--- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
+++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
@@ -147,7 +147,7 @@
"org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.chatbot";
/**
- * The service ID used to indicate that the Standalone Messaging is available.
+ * The service ID used to indicate that the Chatbot using Standalone Messaging is available.
* <p>
* See the GSMA RCC.07 specification for more information.
*/
@@ -161,6 +161,14 @@
*/
public static final String SERVICE_ID_CHATBOT_ROLE = "org.gsma.rcs.isbot";
+ /**
+ * The service ID used to indicate that the Standalone Messaging is available.
+ * <p>
+ * See the GSMA RCC.07 RCS5_1_advanced_communications_specification_v4.0 specification
+ * for more information.
+ */
+ public static final String SERVICE_ID_SLM = "org.openmobilealliance:StandaloneMsg";
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "SERVICE_ID_", value = {
@@ -177,7 +185,8 @@
SERVICE_ID_SHARED_SKETCH,
SERVICE_ID_CHATBOT,
SERVICE_ID_CHATBOT_STANDALONE,
- SERVICE_ID_CHATBOT_ROLE
+ SERVICE_ID_CHATBOT_ROLE,
+ SERVICE_ID_SLM
})
public @interface ServiceId {}
diff --git a/telephony/java/android/telephony/ims/SipDetails.java b/telephony/java/android/telephony/ims/SipDetails.java
index 6ec5afb..fe58eb3 100644
--- a/telephony/java/android/telephony/ims/SipDetails.java
+++ b/telephony/java/android/telephony/ims/SipDetails.java
@@ -37,12 +37,15 @@
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "METHOD_", value = {
+ METHOD_UNKNOWN,
METHOD_REGISTER,
METHOD_PUBLISH,
METHOD_SUBSCRIBE
})
public @interface Method {}
+ public static final int METHOD_UNKNOWN = 0;
+
/**
* Indicates information related to the SIP registration method.
* See RFC 3261 for details.
@@ -97,14 +100,14 @@
}
/**
- * Sets the sip response code and reason response for this SIP method.
+ * Sets the SIP response code and reason response for this SIP method.
* Ref RFC3261 Section 21.
* @param responseCode The SIP response code sent from the network for the
* operation token specified.
* @param responsePhrase The optional reason response from the network. If
* there is a reason header included in the response, that should take
* precedence over the reason provided in the status line. If the network
- * provided no reason with the sip code, the string should be empty.
+ * provided no reason with the SIP code, the string should be empty.
* @return The same instance of the builder.
*/
public Builder setSipResponseCode(int responseCode,
@@ -170,13 +173,16 @@
}
/**
+ * Get the method type of this instance.
* @return The method type associated with this SIP information.
*/
- public int getMethod() {
+ public @Method int getMethod() {
return mMethod;
}
/**
+ * Get the value of CSeq header field.
+ * The CSeq header field serves as a way to identify and order transactions.
* @return The command sequence value associated with this SIP information.
*/
public int getCSeq() {
@@ -184,35 +190,48 @@
}
/**
- * @return The sip response code associated with this SIP information.
+ * Get the value of response code from the SIP response.
+ * The SIP response code sent from the network for the operation token specified.
+ * @return The SIP response code associated with this SIP information.
*/
public int getResponseCode() {
return mResponseCode;
}
/**
- * @return The optional reason response associated with this SIP information.
+ * Get the value of reason from the SIP response.
+ * The optional reason response from the network. If
+ * there is a reason header included in the response, that should take
+ * precedence over the reason provided in the status line.
+ * @return The optional reason response associated with this SIP information. If the network
+ * provided no reason with the SIP code, the string should be empty.
*/
public @NonNull String getResponsePhrase() {
return mResponsePhrase;
}
/**
- * @return The "cause" parameter of the reason header included in the SIP message
+ * Get the "cause" parameter of the "reason" header.
+ * @return The "cause" parameter of the reason header. If the SIP message from the network
+ * does not have a reason header, it should be 0.
*/
public int getReasonHeaderCause() {
return mReasonHeaderCause;
}
/**
- * @return The "text" parameter of the reason header included in the SIP message.
+ * Get the "text" parameter of the "reason" header in the SIP message.
+ * @return The "text" parameter of the reason header. If the SIP message from the network
+ * does not have a reason header, it can be empty.
*/
public @NonNull String getReasonHeaderText() {
return mReasonHeaderText;
}
/**
- * @return The Call-ID value associated with this SIP information.
+ * Get the value of the Call-ID header field for this SIP method.
+ * @return The Call-ID value associated with this SIP information. If the Call-ID value is
+ * not set when ImsService notifies the framework, this value will be null.
*/
public @Nullable String getCallId() {
return mCallId;
diff --git a/telephony/java/android/telephony/satellite/PointingInfo.java b/telephony/java/android/telephony/satellite/PointingInfo.java
new file mode 100644
index 0000000..d6dd57a
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/PointingInfo.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public final class PointingInfo implements Parcelable {
+ /** Satellite azimuth in degrees */
+ private float mSatelliteAzimuthDegrees;
+
+ /** Satellite elevation in degrees */
+ private float mSatelliteElevationDegrees;
+
+ /** Antenna azimuth in degrees */
+ private float mAntennaAzimuthDegrees;
+
+ /**
+ * Angle of rotation about the x axis. This value represents the angle between a plane
+ * parallel to the device's screen and a plane parallel to the ground.
+ */
+ private float mAntennaPitchDegrees;
+
+ /**
+ * Angle of rotation about the y axis. This value represents the angle between a plane
+ * perpendicular to the device's screen and a plane parallel to the ground.
+ */
+ private float mAntennaRollDegrees;
+
+ /**
+ * @hide
+ */
+ public PointingInfo(float satelliteAzimuthDegress, float satelliteElevationDegress,
+ float antennaAzimuthDegrees, float antennaPitchDegrees, float antennaRollDegrees) {
+ mSatelliteAzimuthDegrees = satelliteAzimuthDegress;
+ mSatelliteElevationDegrees = satelliteElevationDegress;
+ mAntennaAzimuthDegrees = antennaAzimuthDegrees;
+ mAntennaPitchDegrees = antennaPitchDegrees;
+ mAntennaRollDegrees = antennaRollDegrees;
+ }
+
+ private PointingInfo(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeFloat(mSatelliteAzimuthDegrees);
+ out.writeFloat(mSatelliteElevationDegrees);
+ out.writeFloat(mAntennaAzimuthDegrees);
+ out.writeFloat(mAntennaPitchDegrees);
+ out.writeFloat(mAntennaRollDegrees);
+ }
+
+ public static final @android.annotation.NonNull Creator<PointingInfo> CREATOR =
+ new Creator<PointingInfo>() {
+ @Override
+ public PointingInfo createFromParcel(Parcel in) {
+ return new PointingInfo(in);
+ }
+
+ @Override
+ public PointingInfo[] newArray(int size) {
+ return new PointingInfo[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("SatelliteAzimuthDegrees:");
+ sb.append(mSatelliteAzimuthDegrees);
+ sb.append(",");
+
+ sb.append("SatelliteElevationDegrees:");
+ sb.append(mSatelliteElevationDegrees);
+ sb.append(",");
+
+ sb.append("AntennaAzimuthDegrees:");
+ sb.append(mAntennaAzimuthDegrees);
+ sb.append(",");
+
+ sb.append("AntennaPitchDegrees:");
+ sb.append(mAntennaPitchDegrees);
+ sb.append(",");
+
+ sb.append("AntennaRollDegrees:");
+ sb.append(mAntennaRollDegrees);
+ return sb.toString();
+ }
+
+ public float getSatelliteAzimuthDegrees() {
+ return mSatelliteAzimuthDegrees;
+ }
+
+ public float getSatelliteElevationDegrees() {
+ return mSatelliteElevationDegrees;
+ }
+
+ public float getAntennaAzimuthDegrees() {
+ return mAntennaAzimuthDegrees;
+ }
+
+ public float getAntennaPitchDegrees() {
+ return mAntennaPitchDegrees;
+ }
+
+ public float getAntennaRollDegrees() {
+ return mAntennaRollDegrees;
+ }
+
+ private void readFromParcel(Parcel in) {
+ mSatelliteAzimuthDegrees = in.readFloat();
+ mSatelliteElevationDegrees = in.readFloat();
+ mAntennaAzimuthDegrees = in.readFloat();
+ mAntennaPitchDegrees = in.readFloat();
+ mAntennaRollDegrees = in.readFloat();
+ }
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
new file mode 100644
index 0000000..c5ae4db
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @hide
+ */
+public final class SatelliteCapabilities implements Parcelable {
+ /**
+ * List of technologies supported by the satellite modem.
+ */
+ private Set<Integer> mSupportedRadioTechnologies;
+
+ /**
+ * Whether satellite mode is always on (this to indicate power impact of keeping it on is
+ * very minimal).
+ */
+ private boolean mIsAlwaysOn;
+
+ /**
+ * Whether UE needs to point to a satellite to send and receive data.
+ */
+ private boolean mNeedsPointingToSatellite;
+
+ /**
+ * List of features supported by the Satellite modem.
+ */
+ private Set<Integer> mSupportedFeatures;
+
+ /**
+ * Whether UE needs a separate SIM profile to communicate with the Satellite network.
+ */
+ private boolean mNeedsSeparateSimProfile;
+
+ /**
+ * @hide
+ */
+ public SatelliteCapabilities(Set<Integer> supportedRadioTechnologies, boolean isAlwaysOn,
+ boolean needsPointingToSatellite, Set<Integer> supportedFeatures,
+ boolean needsSeparateSimProfile) {
+ mSupportedRadioTechnologies = supportedRadioTechnologies;
+ mIsAlwaysOn = isAlwaysOn;
+ mNeedsPointingToSatellite = needsPointingToSatellite;
+ mSupportedFeatures = supportedFeatures;
+ mNeedsSeparateSimProfile = needsSeparateSimProfile;
+ }
+
+ private SatelliteCapabilities(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ if (mSupportedRadioTechnologies != null && !mSupportedRadioTechnologies.isEmpty()) {
+ out.writeInt(mSupportedRadioTechnologies.size());
+ for (int technology : mSupportedRadioTechnologies) {
+ out.writeInt(technology);
+ }
+ } else {
+ out.writeInt(0);
+ }
+
+ out.writeBoolean(mIsAlwaysOn);
+ out.writeBoolean(mNeedsPointingToSatellite);
+
+ if (mSupportedFeatures != null && !mSupportedFeatures.isEmpty()) {
+ out.writeInt(mSupportedFeatures.size());
+ for (int feature : mSupportedFeatures) {
+ out.writeInt(feature);
+ }
+ } else {
+ out.writeInt(0);
+ }
+
+ out.writeBoolean(mNeedsSeparateSimProfile);
+ }
+
+ public static final @android.annotation.NonNull Creator<SatelliteCapabilities> CREATOR =
+ new Creator<SatelliteCapabilities>() {
+ @Override
+ public SatelliteCapabilities createFromParcel(Parcel in) {
+ return new SatelliteCapabilities(in);
+ }
+
+ @Override
+ public SatelliteCapabilities[] newArray(int size) {
+ return new SatelliteCapabilities[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("SupportedRadioTechnology:");
+ if (mSupportedRadioTechnologies != null && !mSupportedRadioTechnologies.isEmpty()) {
+ for (int technology : mSupportedRadioTechnologies) {
+ sb.append(technology);
+ sb.append(",");
+ }
+ } else {
+ sb.append("none,");
+ }
+
+ sb.append("SupportedFeatures:");
+ if (mSupportedFeatures != null && !mSupportedFeatures.isEmpty()) {
+ for (int feature : mSupportedFeatures) {
+ sb.append(feature);
+ sb.append(",");
+ }
+ } else {
+ sb.append("none,");
+ }
+
+ sb.append("isAlwaysOn:");
+ sb.append(mIsAlwaysOn);
+ sb.append(",");
+
+ sb.append("needsPointingToSatellite:");
+ sb.append(mNeedsPointingToSatellite);
+ sb.append(",");
+
+ sb.append("needsSeparateSimProfile:");
+ sb.append(mNeedsSeparateSimProfile);
+ return sb.toString();
+ }
+
+ @NonNull
+ public Set<Integer> getSupportedRadioTechnologies() {
+ return mSupportedRadioTechnologies;
+ }
+
+ public boolean isAlwaysOn() {
+ return mIsAlwaysOn;
+ }
+
+ /** Get function for mNeedsPointingToSatellite */
+ public boolean needsPointingToSatellite() {
+ return mNeedsPointingToSatellite;
+ }
+
+ @NonNull
+ public Set<Integer> getSupportedFeatures() {
+ return mSupportedFeatures;
+ }
+
+ /** Get function for mNeedsSeparateSimProfile */
+ public boolean needsSeparateSimProfile() {
+ return mNeedsSeparateSimProfile;
+ }
+
+ private void readFromParcel(Parcel in) {
+ mSupportedRadioTechnologies = new HashSet<>();
+ int numSupportedRadioTechnologies = in.readInt();
+ if (numSupportedRadioTechnologies > 0) {
+ for (int i = 0; i < numSupportedRadioTechnologies; i++) {
+ mSupportedRadioTechnologies.add(in.readInt());
+ }
+ }
+
+ mIsAlwaysOn = in.readBoolean();
+ mNeedsPointingToSatellite = in.readBoolean();
+
+ mSupportedFeatures = new HashSet<>();
+ int numSupportedFeatures = in.readInt();
+ if (numSupportedFeatures > 0) {
+ for (int i = 0; i < numSupportedFeatures; i++) {
+ mSupportedFeatures.add(in.readInt());
+ }
+ }
+
+ mNeedsSeparateSimProfile = in.readBoolean();
+ }
+}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
new file mode 100644
index 0000000..d3964a8
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.satellite.stub;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * @hide
+ */
+public class SatelliteImplBase {
+ private static final String TAG = "SatelliteImplBase";
+
+ /**@hide*/
+ @IntDef(
+ prefix = "TECHNOLOGY_",
+ value = {
+ TECHNOLOGY_NB_IOT_NTN,
+ TECHNOLOGY_NR_NTN,
+ TECHNOLOGY_EMTC_NTN,
+ TECHNOLOGY_PROPRIETARY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NTRadioTechnology {}
+
+ /** 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology */
+ public static final int TECHNOLOGY_NB_IOT_NTN =
+ android.hardware.radio.satellite.NTRadioTechnology.NB_IOT_NTN;
+ /** 3GPP 5G NR over Non-Terrestrial-Networks technology */
+ public static final int TECHNOLOGY_NR_NTN =
+ android.hardware.radio.satellite.NTRadioTechnology.NR_NTN;
+ /** 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology */
+ public static final int TECHNOLOGY_EMTC_NTN =
+ android.hardware.radio.satellite.NTRadioTechnology.EMTC_NTN;
+ /** Proprietary technology like Iridium or Bullitt */
+ public static final int TECHNOLOGY_PROPRIETARY =
+ android.hardware.radio.satellite.NTRadioTechnology.PROPRIETARY;
+
+ /**@hide*/
+ @IntDef(
+ prefix = "FEATURE_",
+ value = {
+ FEATURE_SOS_SMS,
+ FEATURE_EMERGENCY_SMS,
+ FEATURE_SMS,
+ FEATURE_LOCATION_SHARING,
+ FEATURE_UNKNOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Feature {}
+
+ /** Able to send and receive SMS messages to/from SOS numbers like call/service centers */
+ public static final int FEATURE_SOS_SMS =
+ android.hardware.radio.satellite.SatelliteFeature.SOS_SMS;
+ /** Able to send and receive SMS messages to/from emergency numbers like 911 */
+ public static final int FEATURE_EMERGENCY_SMS =
+ android.hardware.radio.satellite.SatelliteFeature.EMERGENCY_SMS;
+ /** Able to send and receive SMS messages to/from any allowed contacts */
+ public static final int FEATURE_SMS = android.hardware.radio.satellite.SatelliteFeature.SMS;
+ /** Able to send device location to allowed contacts */
+ public static final int FEATURE_LOCATION_SHARING =
+ android.hardware.radio.satellite.SatelliteFeature.LOCATION_SHARING;
+ /** This feature is not defined in satellite HAL APIs */
+ public static final int FEATURE_UNKNOWN = 0xFFFF;
+
+ /**@hide*/
+ @IntDef(
+ prefix = "MODE_",
+ value = {
+ MODE_POWERED_OFF,
+ MODE_OUT_OF_SERVICE_NOT_SEARCHING,
+ MODE_OUT_OF_SERVICE_SEARCHING,
+ MODE_ACQUIRED,
+ MODE_MESSAGE_TRANSFERRING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Mode {}
+
+ /** Satellite modem is powered off */
+ public static final int MODE_POWERED_OFF =
+ android.hardware.radio.satellite.SatelliteMode.POWERED_OFF;
+ /** Satellite modem is in out of service state and not searching for satellite signal */
+ public static final int MODE_OUT_OF_SERVICE_NOT_SEARCHING =
+ android.hardware.radio.satellite.SatelliteMode.OUT_OF_SERVICE_NOT_SEARCHING;
+ /** Satellite modem is in out of service state and searching for satellite signal */
+ public static final int MODE_OUT_OF_SERVICE_SEARCHING =
+ android.hardware.radio.satellite.SatelliteMode.OUT_OF_SERVICE_SEARCHING;
+ /** Satellite modem has found satellite signal and gets connected to the satellite network */
+ public static final int MODE_ACQUIRED = android.hardware.radio.satellite.SatelliteMode.ACQUIRED;
+ /** Satellite modem is sending and/or receiving messages */
+ public static final int MODE_MESSAGE_TRANSFERRING =
+ android.hardware.radio.satellite.SatelliteMode.MESSAGE_TRANSFERRING;
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c7ed347..6099cb1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2687,4 +2687,9 @@
* @return {@code true} if the domain selection service is supported.
*/
boolean isDomainSelectionSupported();
+
+ /**
+ * Get the carrier restriction status of the device.
+ */
+ void getCarrierRestrictionStatus(IIntegerConsumer internalCallback, String packageName);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a9af199..6e56963 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -546,6 +546,22 @@
int RIL_REQUEST_UPDATE_IMS_CALL_STATUS = 240;
int RIL_REQUEST_SET_N1_MODE_ENABLED = 241;
int RIL_REQUEST_IS_N1_MODE_ENABLED = 242;
+ int RIL_REQUEST_SET_LOCATION_PRIVACY_SETTING = 243;
+ int RIL_REQUEST_GET_LOCATION_PRIVACY_SETTING = 244;
+ int RIL_REQUEST_GET_SATELLITE_CAPABILITIES = 245;
+ int RIL_REQUEST_SET_SATELLITE_POWER = 246;
+ int RIL_REQUEST_GET_SATELLITE_POWER = 247;
+ int RIL_REQUEST_PROVISION_SATELLITE_SERVICE = 248;
+ int RIL_REQUEST_ADD_ALLOWED_SATELLITE_CONTACTS = 249;
+ int RIL_REQUEST_REMOVE_ALLOWED_SATELLITE_CONTACTS = 250;
+ int RIL_REQUEST_SEND_SATELLITE_MESSAGES = 251;
+ int RIL_REQUEST_GET_PENDING_SATELLITE_MESSAGES = 252;
+ int RIL_REQUEST_GET_SATELLITE_MODE = 253;
+ int RIL_REQUEST_SET_SATELLITE_INDICATION_FILTER = 254;
+ int RIL_REQUEST_START_SENDING_SATELLITE_POINTING_INFO = 255;
+ int RIL_REQUEST_STOP_SENDING_SATELLITE_POINTING_INFO = 256;
+ int RIL_REQUEST_GET_MAX_CHARACTERS_PER_SATELLITE_TEXT_MESSAGE = 257;
+ int RIL_REQUEST_GET_TIME_FOR_NEXT_SATELLITE_VISIBILITY = 258;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
@@ -607,6 +623,13 @@
int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_CHANGED = 1053;
int RIL_UNSOL_RESPONSE_SIM_PHONEBOOK_RECORDS_RECEIVED = 1054;
int RIL_UNSOL_SLICING_CONFIG_CHANGED = 1055;
+ int RIL_UNSOL_PENDING_SATELLITE_MESSAGE_COUNT = 1056;
+ int RIL_UNSOL_NEW_SATELLITE_MESSAGES = 1057;
+ int RIL_UNSOL_SATELLITE_MESSAGES_TRANSFER_COMPLETE = 1058;
+ int RIL_UNSOL_SATELLITE_POINTING_INFO_CHANGED = 1059;
+ int RIL_UNSOL_SATELLITE_MODE_CHANGED = 1060;
+ int RIL_UNSOL_SATELLITE_RADIO_TECHNOLOGY_CHANGED = 1061;
+ int RIL_UNSOL_SATELLITE_PROVISION_STATE_CHANGED = 1062;
/* The following unsols are not defined in RIL.h */
int RIL_UNSOL_HAL_NON_RIL_BASE = 1100;
diff --git a/tests/FlickerTests/AndroidManifest.xml b/tests/FlickerTests/AndroidManifest.xml
index 487a0c3..462f91b 100644
--- a/tests/FlickerTests/AndroidManifest.xml
+++ b/tests/FlickerTests/AndroidManifest.xml
@@ -43,7 +43,7 @@
<!-- ActivityOptions.makeCustomTaskAnimation() -->
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<!-- Allow the test to write directly to /sdcard/ -->
- <application android:requestLegacyExternalStorage="true">
+ <application android:requestLegacyExternalStorage="true" android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<uses-library android:name="androidx.window.extensions" android:required="false"/>
</application>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index 8fe6aac..18792a8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -103,6 +103,54 @@
}
/**
+ * Minimizes the PIP window my using the pinch in gesture.
+ *
+ * @param percent The percentage by which to decrease the pip window size.
+ * @throws IllegalArgumentException if percentage isn't between 0.0f and 1.0f
+ */
+ fun pinchInPipWindow(wmHelper: WindowManagerStateHelper, percent: Float, steps: Int) {
+ // the percentage must be between 0.0f and 1.0f
+ if (percent <= 0.0f || percent > 1.0f) {
+ throw IllegalArgumentException("Percent must be between 0.0f and 1.0f")
+ }
+
+ val windowRect = getWindowRect(wmHelper)
+
+ // first pointer's initial x coordinate is halfway between the left edge and the center
+ val initLeftX = (windowRect.centerX() - windowRect.width / 4).toFloat()
+ // second pointer's initial x coordinate is halfway between the right edge and the center
+ val initRightX = (windowRect.centerX() + windowRect.width / 4).toFloat()
+
+ // decrease by the distance specified through the percentage
+ val distDecrease = windowRect.width * percent
+
+ // get the final x-coordinates and make sure they are not passing the center of the window
+ val finalLeftX = Math.min(initLeftX + (distDecrease / 2), windowRect.centerX().toFloat())
+ val finalRightX = Math.max(initRightX - (distDecrease / 2), windowRect.centerX().toFloat())
+
+ // y-coordinate is the same throughout this animation
+ val yCoord = windowRect.centerY().toFloat()
+
+ var adjustedSteps = MIN_STEPS_TO_ANIMATE
+
+ // if distance per step is at least 1, then we can use the number of steps requested
+ if (distDecrease.toInt() / (steps * 2) >= 1) {
+ adjustedSteps = steps
+ }
+
+ // if the distance per step is less than 1, carry out the animation in two steps
+ gestureHelper.pinch(
+ Tuple(initLeftX, yCoord),
+ Tuple(initRightX, yCoord),
+ Tuple(finalLeftX, yCoord),
+ Tuple(finalRightX, yCoord),
+ adjustedSteps
+ )
+
+ waitForPipWindowToMinimizeFrom(wmHelper, Region.from(windowRect))
+ }
+
+ /**
* Launches the app through an intent instead of interacting with the launcher and waits until
* the app window is in PIP mode
*/
@@ -238,6 +286,24 @@
.waitForAndVerify()
}
+ private fun waitForPipWindowToMinimizeFrom(
+ wmHelper: WindowManagerStateHelper,
+ windowRect: Region
+ ) {
+ wmHelper
+ .StateSyncBuilder()
+ .add("pipWindowMinimized") {
+ val pipAppWindow =
+ it.wmState.visibleWindows.firstOrNull { window ->
+ this.windowMatchesAnyOf(window)
+ }
+ ?: return@add false
+ val pipRegion = pipAppWindow.frameRegion
+ return@add windowRect.coversMoreThan(pipRegion)
+ }
+ .waitForAndVerify()
+ }
+
companion object {
private const val TAG = "PipAppHelper"
private const val ENTER_PIP_BUTTON_ID = "enter_pip"
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 616f21cb..fdba9a6 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -1163,5 +1163,13 @@
<category android:name="com.android.test.hwui.TEST"/>
</intent-filter>
</activity>
+ <activity android:name="MeshLargeActivity"
+ android:label="Mesh/LargeMesh"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java
new file mode 100644
index 0000000..f97d942
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MeshLargeActivity.java
@@ -0,0 +1,175 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.BlendMode;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Mesh;
+import android.graphics.MeshSpecification;
+import android.graphics.MeshSpecification.Attribute;
+import android.graphics.MeshSpecification.Varying;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.View;
+
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+import java.util.ArrayList;
+
+public class MeshLargeActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new MeshView(this));
+ }
+
+ static class MeshView extends View {
+ MeshView(Context c) {
+ super(c);
+ this.setOnTouchListener((v, event) -> {
+ invalidate();
+ return true;
+ });
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ MeshSpecification meshSpec = createMeshSpecification();
+ int numTriangles = 10000;
+ // number of triangles plus first 2 vertices
+ FloatBuffer vertexBuffer = FloatBuffer.allocate((numTriangles + 2) * 30);
+ ShortBuffer indexBuffer = ShortBuffer.allocate(numTriangles * 3);
+
+ float origin = 500.0f;
+ int radius = 200;
+
+ // origin
+ vertexBuffer.put(0, origin);
+ vertexBuffer.put(1, origin);
+ for (int i = 0; i < 7; i++) {
+ vertexBuffer.put(2 + (i * 4), 1.0f);
+ vertexBuffer.put(2 + (i * 4) + 1, 1.0f);
+ vertexBuffer.put(2 + (i * 4) + 2, 1.0f);
+ vertexBuffer.put(2 + (i * 4) + 3, 1.0f);
+ }
+
+ // first point
+ vertexBuffer.put(30, origin + radius);
+ vertexBuffer.put(31, origin);
+ for (int i = 0; i < 7; i++) {
+ vertexBuffer.put(32 + (i * 4), 1.0f);
+ vertexBuffer.put(32 + (i * 4) + 1, 1.0f);
+ vertexBuffer.put(32 + (i * 4) + 2, 1.0f);
+ vertexBuffer.put(32 + (i * 4) + 3, 1.0f);
+ }
+
+ int nVert = 2;
+ int nInd = 0;
+ for (int i = 2; i <= numTriangles + 1; i++) {
+ double angle = 2 * Math.PI * i / numTriangles;
+ double x = radius * Math.cos(angle);
+ double y = radius * Math.sin(angle);
+ // position
+ vertexBuffer.put(i * 30, origin + (float) x);
+ vertexBuffer.put(i * 30 + 1, origin + (float) y);
+
+ // test through test7
+ for (int j = 0; j < 7; j++) {
+ vertexBuffer.put((i * 30 + 2) + (j * 4), 1.0f);
+ vertexBuffer.put((i * 30 + 2) + (j * 4) + 1, 1.0f);
+ vertexBuffer.put((i * 30 + 2) + (j * 4) + 2, 1.0f);
+ vertexBuffer.put((i * 30 + 2) + (j * 4) + 3, 1.0f);
+ }
+
+ indexBuffer.put(nInd++, (short) 0);
+ indexBuffer.put(nInd++, (short) (nVert - 1));
+ indexBuffer.put(nInd++, (short) nVert);
+ nVert++;
+ }
+ vertexBuffer.rewind();
+ indexBuffer.rewind();
+ Mesh mesh = Mesh.makeIndexed(
+ meshSpec, Mesh.TRIANGLES, vertexBuffer, numTriangles + 2, indexBuffer,
+ new Rect(0, 0, 1000, 1000)
+ );
+ mesh.setFloatUniform("test", 1.0f, 2.0f);
+ Paint paint = new Paint();
+ paint.setColor(Color.BLUE);
+
+ canvas.drawMesh(mesh, BlendMode.SRC, paint);
+ }
+
+ private MeshSpecification createMeshSpecification() {
+ String vs = "Varyings main(const Attributes attributes) { "
+ + " Varyings varyings;"
+ + " varyings.position = attributes.position;"
+ + " return varyings;"
+ + "}";
+ String fs = "uniform float2 test;"
+ + "float2 main(const Varyings varyings, out float4 color) {\n"
+ + " color = vec4(1.0, 0.0, 0.0, 1.0);"
+ + " return varyings.position;\n"
+ + "}";
+ ArrayList<Attribute> attList = new ArrayList<>();
+ attList.add(new Attribute(MeshSpecification.FLOAT2, 0, "position"));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 8,
+ "test"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 24,
+ "test2"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 40,
+ "test3"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 56,
+ "test4"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 72,
+ "test5"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 88,
+ "test6"
+ ));
+ attList.add(new Attribute(
+ MeshSpecification.FLOAT4,
+ 104,
+ "test7"
+ ));
+ ArrayList<Varying> varyList = new ArrayList<>();
+ return MeshSpecification.make(attList, 120, varyList, vs, fs);
+ }
+ }
+}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
index ddcc811..d075b5f 100644
--- a/tests/Input/src/com/android/test/input/InputDeviceTest.java
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.hardware.input.HostUsiVersion;
import android.os.Parcel;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -57,6 +58,8 @@
assertEquals(device.getKeyboardLanguageTag(), outDevice.getKeyboardLanguageTag());
assertEquals(device.getKeyboardLayoutType(), outDevice.getKeyboardLayoutType());
assertEquals(device.getMotionRanges().size(), outDevice.getMotionRanges().size());
+ assertEquals(device.getHostUsiVersion(), outDevice.getHostUsiVersion());
+ assertEquals(device.getAssociatedDisplayId(), outDevice.getAssociatedDisplayId());
KeyCharacterMap keyCharacterMap = device.getKeyCharacterMap();
KeyCharacterMap outKeyCharacterMap = outDevice.getKeyCharacterMap();
@@ -88,7 +91,7 @@
.setHasBattery(true)
.setKeyboardLanguageTag("en-US")
.setKeyboardLayoutType("qwerty")
- .setSupportsUsi(true);
+ .setUsiVersion(new HostUsiVersion(2, 0));
for (int i = 0; i < 30; i++) {
deviceBuilder.addMotionRange(
diff --git a/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java b/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
index bf6ece1..e704cc2 100644
--- a/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
+++ b/tests/Internal/src/com/android/internal/app/LocaleStoreTest.java
@@ -17,8 +17,10 @@
package com.android.internal.app;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.os.LocaleList;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
@@ -27,23 +29,21 @@
import com.android.internal.app.LocaleStore.LocaleInfo;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.IllformedLocaleException;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
-/**
- * Unit tests for the {@link LocaleStore}.
- */
+/** Unit tests for the {@link LocaleStore}. */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class LocaleStoreTest {
- @Before
- public void setUp() {
- }
-
@Test
public void testTransformImeLanguageTagToLocaleInfo() {
List<InputMethodSubtype> list = List.of(
@@ -60,4 +60,99 @@
assertTrue(expectedLanguageTag.contains(info.getId()));
}
}
+
+ @Test
+ public void convertExplicitLocales_noExplicitLcoales_returnEmptyHashMap() {
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(
+ LocaleList.getEmptyLocaleList(), supportedLocale);
+
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ public void convertExplicitLocales_hasEmptyLocale_receiveException() {
+ Locale[] locales = {Locale.forLanguageTag(""), Locale.forLanguageTag("en-US")};
+ LocaleList localelist = new LocaleList(locales);
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ boolean isReceiveException = false;
+ try {
+ LocaleStore.convertExplicitLocales(localelist, supportedLocale);
+ } catch (IllformedLocaleException e) {
+ isReceiveException = true;
+ }
+
+ assertTrue(isReceiveException);
+ }
+
+ @Test
+ public void convertExplicitLocales_hasSameLocale_returnNonSameLocales() {
+ LocaleList locales = LocaleList.forLanguageTags("en-US,en-US");
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(locales, supportedLocale);
+
+ // Only has "en" and "en-US".
+ assertTrue(result.size() == 2);
+ }
+
+ @Test
+ public void convertExplicitLocales_hasEnUs_resultHasParentEn() {
+ LocaleList locales = LocaleList.forLanguageTags("en-US,ja-JP");
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(locales, supportedLocale);
+
+ assertEquals(result.get("en").getId(), "en");
+ }
+
+ @Test
+ public void convertExplicitLocales_hasZhTw_resultZhHantTw() {
+ LocaleList locales = LocaleList.forLanguageTags("zh-TW,en-US,en");
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(locales, supportedLocale);
+
+ assertEquals("zh-Hant-TW", result.get("zh-Hant-TW").getId());
+ }
+
+ @Test
+ public void convertExplicitLocales_nonRegularFormat_resultEmptyContry() {
+ LocaleList locales = LocaleList.forLanguageTags("de-1996,de-1901");
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(locales, supportedLocale);
+
+ assertEquals("de-1996", result.get("de-1996").getId());
+ assertTrue(result.get("de-1996").getLocale().getCountry().isEmpty());
+ }
+
+ @Test
+ public void convertExplicitLocales_differentEnFormat() {
+ LocaleList locales = LocaleList.forLanguageTags("en-Latn-US,en-US,en");
+ Collection<LocaleInfo> supportedLocale = getFakeSupportedLocales();
+
+ HashMap<String, LocaleInfo> result =
+ LocaleStore.convertExplicitLocales(locales, supportedLocale);
+
+ assertEquals("en", result.get("en").getId());
+ assertEquals("en-US", result.get("en-US").getId());
+ assertNull(result.get("en-Latn-US"));
+ }
+
+ private ArrayList<LocaleInfo> getFakeSupportedLocales() {
+ String[] locales = {"en-US", "zh-Hant-TW", "ja-JP", "en-GB"};
+ ArrayList<LocaleInfo> supportedLocales = new ArrayList<>();
+ for (String localeTag : locales) {
+ supportedLocales.add(LocaleStore.fromLocale(Locale.forLanguageTag(localeTag)));
+ }
+ return supportedLocales;
+ }
}
diff --git a/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
index 79a2f1f..157d197 100644
--- a/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
+++ b/tests/RollbackTest/SampleRollbackApp/src/com/android/sample/rollbackapp/MainActivity.java
@@ -89,6 +89,7 @@
for (int i = 0; i < mIdsToRollback.size(); i++) {
Intent intent = new Intent(ACTION_NAME);
intent.putExtra(ROLLBACK_ID_EXTRA, mIdsToRollback.get(i));
+ intent.setPackage(getApplicationContext().getPackageName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), 0, intent, FLAG_MUTABLE);
mRollbackManager.commitRollback(mIdsToRollback.get(i),
diff --git a/tools/aapt2/Configuration.proto b/tools/aapt2/Configuration.proto
index 8a4644c..4883844 100644
--- a/tools/aapt2/Configuration.proto
+++ b/tools/aapt2/Configuration.proto
@@ -120,6 +120,13 @@
NAVIGATION_WHEEL = 4;
}
+ enum GrammaticalGender {
+ GRAM_GENDER_USET = 0;
+ GRAM_GENDER_NEUTER = 1;
+ GRAM_GENDER_FEMININE = 2;
+ GRAM_GENDER_MASCULINE = 3;
+ }
+
//
// Axis/dimensions that are understood by the runtime.
//
@@ -198,6 +205,9 @@
// The minimum SDK version of the device.
uint32 sdk_version = 24;
+ // Grammatical gender.
+ GrammaticalGender grammatical_gender = 26;
+
//
// Build-time only dimensions.
//
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index e39f327..09ef9bd 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -354,6 +354,7 @@
out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width());
out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height());
out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version());
+ out_config->grammaticalInflection = pb_config.grammatical_gender();
return true;
}
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 0e40124..0903205 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -275,6 +275,10 @@
}
out_pb_config->set_sdk_version(config.sdkVersion);
+
+ // The constant values are the same across the structs.
+ out_pb_config->set_grammatical_gender(
+ static_cast<pb::Configuration_GrammaticalGender>(config.grammaticalInflection));
}
static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item,
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index ecfdba8..afb8356 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -581,9 +581,13 @@
ExpectConfigSerializes("v8");
+ ExpectConfigSerializes("en-feminine");
+ ExpectConfigSerializes("en-neuter-v34");
+ ExpectConfigSerializes("feminine-v34");
+
ExpectConfigSerializes(
- "mcc123-mnc456-b+en+GB-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-land-car-"
- "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
+ "mcc123-mnc456-b+en+GB-masculine-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-"
+ "land-car-night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
}
TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index f03d6fc..098535d 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -251,7 +251,11 @@
return *this;
}
ConfigDescriptionBuilder& setInputPad0(uint8_t inputPad0) {
- config_.inputPad0 = inputPad0;
+ config_.inputFieldPad0 = inputPad0;
+ return *this;
+ }
+ ConfigDescriptionBuilder& setGrammaticalInflection(uint8_t value) {
+ config_.grammaticalInflection = value;
return *this;
}
ConfigDescriptionBuilder& setScreenWidth(uint16_t screenWidth) {